Data Exploration and Wrangling
The first step in performing any data analysis is to explore the data.
For example, we might want to better understand the variables included in the data, as we may learn about important details about the data that we should keep in mind as we try to predict our outcome variable.
First, let’s just get a general sense of our data. We can do that using the glimpse() function of the dplyr package (it is also in the tibble package).
We will also use the %>% pipe, which can be used to define the input for later sequential steps.
This will make more sense when we have multiple sequential steps using the same data object.
To use the pipe notation we need to install and load dplyr as well.
For example, here we start with pm data object and “pipe” the object into as input into the glimpse() function. The output is is an overview of what is in the pm object such as the number of rows and columns, all the column names, the data types for each column and the first view values in each column. The output below is scrollable so you can see everything from the glimpse() function.
Rows: 876
Columns: 50
$ id <dbl> 1003.001, 1027.000, 1033.100, 1049.100, 1…
$ value <dbl> 9.597647, 10.800000, 11.212174, 11.659091…
$ fips <dbl> 1003, 1027, 1033, 1049, 1055, 1069, 1073,…
$ lat <dbl> 30.49800, 33.28126, 34.75878, 34.28763, 3…
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85.9683…
$ state <chr> "Alabama", "Alabama", "Alabama", "Alabama…
$ county <chr> "Baldwin", "Clay", "Colbert", "DeKalb", "…
$ city <chr> "Fairhope", "Ashland", "Muscle Shoals", "…
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 8.534772, 9…
$ zcta <dbl> 36532, 36251, 35660, 35962, 35901, 36303,…
$ zcta_area <dbl> 190980522, 374132430, 16716984, 203836235…
$ zcta_pop <dbl> 27829, 5103, 9042, 8300, 20045, 30217, 90…
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038, 5.78…
$ imp_a1000 <dbl> 1.4096021, 0.8531574, 11.1448962, 3.86764…
$ imp_a5000 <dbl> 3.3360118, 0.9851479, 15.1786154, 1.23114…
$ imp_a10000 <dbl> 1.9879187, 0.5208189, 9.7253870, 1.031646…
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 0.973044…
$ county_area <dbl> 4117521611, 1564252280, 1534877333, 20126…
$ county_pop <dbl> 182265, 13932, 54428, 71109, 104430, 1015…
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 3.721489, 5…
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 8.517193, 9…
$ log_pri_length_10000 <dbl> 9.210340, 9.210340, 9.274303, 10.409411, …
$ log_pri_length_15000 <dbl> 9.630228, 9.615805, 9.658899, 11.173626, …
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 11.90959, 1…
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 7.310155, 8…
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 8.585843, 9…
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 10.21420…
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 11.50894, 1…
$ log_prisec_length_15000 <dbl> 12.205723, 12.042963, 13.282656, 12.35366…
$ log_prisec_length_25000 <dbl> 13.41395, 12.79980, 13.79973, 13.55979, 1…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.573127301, 0.…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.581917457, 3.…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.887665, 4…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, 0.000…
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, 3.350…
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.171920, 4…
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 35.330814…
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 40.718…
$ nohs <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1, 2.7,…
$ somehs <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 17.1, …
$ hs <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, 37.2,…
$ somecollege <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, 23.5,…
$ associate <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, 8.0, …
$ bachelor <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.9, 17…
$ grad <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, 8.7, …
$ pov <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25.5, 7…
$ hs_orless <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, 61.4,…
$ urc2013 <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ urc2006 <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ aod <dbl> 37.36364, 34.81818, 36.00000, 33.08333, 4…
We can see that there are 876 monitors (rows) and that we have 50 total variables (columns) - one of which is the outcome variable. In this case, the outcome variable is called value.
Notice that some of the variables that we would think of as factors (or categorical data) are currently of class character as indicated by the <chr> just to the right of the column names/variable names in the glimpse() output. This means that the variable values are character strings, such as words or phrases.
The other variables are of class <dbl>, which stands for double precision which indicates that the are numeric and that they have decimal values. In contrast, one could have integer values which would not allow for decimal numbers. Here is a link for more information on double precision numeric values.
Another common data class is factor which is abbreviated like this: <fct>. A factor is something that has unique levels but there is no appreciable order to the levels. For example we can have a numeric value that is just an id that we want to be interpreted as just a unique level and not as the number that it would typically indicate. This would be useful for several of our variables:
- the monitor ID (
id)
- the Federal Information Processing Standard number for the county where the monitor was located (
fips)
- the zip code tabulation area (
zcta)
None of the values actually have any real numeric meaning, so we want to make sure that R does not interpret them as if they do.
So let’s convert these variables into factors. We can do this using the across() function of the dplyr package and the as.factor() base function. The across() function has two main arguments: (i) the columns you want to operate on and (ii) the function or list of functions to apply to each column.
In this case, we are also using the magrittr assignment pipe or double pipe that looks like this %<>% of the magrittr package. This allows us use the pm data as input, but also reassigns the output to the same data object name.
Rows: 876
Columns: 50
$ id <fct> 1003.001, 1027.0001, 1033.1002, 1049.1003…
$ value <dbl> 9.597647, 10.800000, 11.212174, 11.659091…
$ fips <fct> 1003, 1027, 1033, 1049, 1055, 1069, 1073,…
$ lat <dbl> 30.49800, 33.28126, 34.75878, 34.28763, 3…
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85.9683…
$ state <chr> "Alabama", "Alabama", "Alabama", "Alabama…
$ county <chr> "Baldwin", "Clay", "Colbert", "DeKalb", "…
$ city <chr> "Fairhope", "Ashland", "Muscle Shoals", "…
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 8.534772, 9…
$ zcta <fct> 36532, 36251, 35660, 35962, 35901, 36303,…
$ zcta_area <dbl> 190980522, 374132430, 16716984, 203836235…
$ zcta_pop <dbl> 27829, 5103, 9042, 8300, 20045, 30217, 90…
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038, 5.78…
$ imp_a1000 <dbl> 1.4096021, 0.8531574, 11.1448962, 3.86764…
$ imp_a5000 <dbl> 3.3360118, 0.9851479, 15.1786154, 1.23114…
$ imp_a10000 <dbl> 1.9879187, 0.5208189, 9.7253870, 1.031646…
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 0.973044…
$ county_area <dbl> 4117521611, 1564252280, 1534877333, 20126…
$ county_pop <dbl> 182265, 13932, 54428, 71109, 104430, 1015…
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 3.721489, 5…
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 8.517193, 9…
$ log_pri_length_10000 <dbl> 9.210340, 9.210340, 9.274303, 10.409411, …
$ log_pri_length_15000 <dbl> 9.630228, 9.615805, 9.658899, 11.173626, …
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 11.90959, 1…
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 7.310155, 8…
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 8.585843, 9…
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 10.21420…
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 11.50894, 1…
$ log_prisec_length_15000 <dbl> 12.205723, 12.042963, 13.282656, 12.35366…
$ log_prisec_length_25000 <dbl> 13.41395, 12.79980, 13.79973, 13.55979, 1…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.573127301, 0.…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.581917457, 3.…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.887665, 4…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, 0.000…
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, 3.350…
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.171920, 4…
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 35.330814…
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 40.718…
$ nohs <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1, 2.7,…
$ somehs <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 17.1, …
$ hs <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, 37.2,…
$ somecollege <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, 23.5,…
$ associate <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, 8.0, …
$ bachelor <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.9, 17…
$ grad <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, 8.7, …
$ pov <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25.5, 7…
$ hs_orless <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, 61.4,…
$ urc2013 <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ urc2006 <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ aod <dbl> 37.36364, 34.81818, 36.00000, 33.08333, 4…
Great! Now we can see that these variables are now factors as indicated by <fct> after the variable name.
Skim package
The skim() function of the skimr package is also really helpful for getting a general sense of your data. By design, it provides summary statistics about variables in the data set.
Notice how there is a column called n_missing about the number of values that are missing.
This is also indicated by the complete_rate variable (or missing/number of observations).
In our data set, it looks like our data do not contain any missing data.
Also notice how the function provides separate tables of summary statistics for each data type: character, factor and numeric.
Next, the n_unqiue column shows us the number of unique values for each of our columns. We can see that there are 49 states represented in the data.
We can see that for many variables there are many low values as the distribution shows two peaks, one near zero and another with a higher value.
This is true for the imp variables (measures of development), the nei variables (measures of emission sources) and the road density variables.
We can also see that the range of some of the variables is very large, in particular the area and population related variables.
Let’s take a look to see which states are included using the distinct() function of the dplyr package:
Scroll through the output:
It looks like “District of Columbia” is being included as a state. We can see that Alaska and Hawaii are not included in the data.
Let’s also take a look to see how many monitors there are in a few cities. We can use the filter() function of the dplyr package to do so. For example, let’s look at Albuquerque, New Mexico.
# A tibble: 2 x 50
id value fips lat lon state county city CMAQ zcta zcta_area
<fct> <dbl> <fct> <dbl> <dbl> <chr> <chr> <chr> <dbl> <fct> <dbl>
1 3500… 5.98 35001 35.1 -107. New … Berna… Albu… 10.1 87109 26199125
2 3500… 5.91 35001 35.1 -107. New … Berna… Albu… 10.1 87108 15224438
# … with 39 more variables: zcta_pop <dbl>, imp_a500 <dbl>, imp_a1000 <dbl>,
# imp_a5000 <dbl>, imp_a10000 <dbl>, imp_a15000 <dbl>, county_area <dbl>,
# county_pop <dbl>, log_dist_to_prisec <dbl>, log_pri_length_5000 <dbl>,
# log_pri_length_10000 <dbl>, log_pri_length_15000 <dbl>,
# log_pri_length_25000 <dbl>, log_prisec_length_500 <dbl>,
# log_prisec_length_1000 <dbl>, log_prisec_length_5000 <dbl>,
# log_prisec_length_10000 <dbl>, log_prisec_length_15000 <dbl>,
# log_prisec_length_25000 <dbl>, log_nei_2008_pm25_sum_10000 <dbl>,
# log_nei_2008_pm25_sum_15000 <dbl>, log_nei_2008_pm25_sum_25000 <dbl>,
# log_nei_2008_pm10_sum_10000 <dbl>, log_nei_2008_pm10_sum_15000 <dbl>,
# log_nei_2008_pm10_sum_25000 <dbl>, popdens_county <dbl>,
# popdens_zcta <dbl>, nohs <dbl>, somehs <dbl>, hs <dbl>, somecollege <dbl>,
# associate <dbl>, bachelor <dbl>, grad <dbl>, pov <dbl>, hs_orless <dbl>,
# urc2013 <dbl>, urc2006 <dbl>, aod <dbl>
We can see that there were only two monitors in the city of Albuquerque in 2006. Let’s compare this with Baltimore.
# A tibble: 5 x 50
id value fips lat lon state county city CMAQ zcta zcta_area
<fct> <dbl> <fct> <dbl> <dbl> <chr> <chr> <chr> <dbl> <fct> <dbl>
1 2451… 12.2 24510 39.3 -76.6 Mary… Balti… Balt… 10.9 21251 461424
2 2451… 12.5 24510 39.3 -76.7 Mary… Balti… Balt… 10.9 21215 17645223
3 2451… 12.8 24510 39.3 -76.5 Mary… Balti… Balt… 10.9 21224 24539976
4 2451… 14.3 24510 39.2 -76.6 Mary… Balti… Balt… 10.9 21226 25718732
5 2451… 13.3 24510 39.3 -76.6 Mary… Balti… Balt… 10.9 21202 4111039
# … with 39 more variables: zcta_pop <dbl>, imp_a500 <dbl>, imp_a1000 <dbl>,
# imp_a5000 <dbl>, imp_a10000 <dbl>, imp_a15000 <dbl>, county_area <dbl>,
# county_pop <dbl>, log_dist_to_prisec <dbl>, log_pri_length_5000 <dbl>,
# log_pri_length_10000 <dbl>, log_pri_length_15000 <dbl>,
# log_pri_length_25000 <dbl>, log_prisec_length_500 <dbl>,
# log_prisec_length_1000 <dbl>, log_prisec_length_5000 <dbl>,
# log_prisec_length_10000 <dbl>, log_prisec_length_15000 <dbl>,
# log_prisec_length_25000 <dbl>, log_nei_2008_pm25_sum_10000 <dbl>,
# log_nei_2008_pm25_sum_15000 <dbl>, log_nei_2008_pm25_sum_25000 <dbl>,
# log_nei_2008_pm10_sum_10000 <dbl>, log_nei_2008_pm10_sum_15000 <dbl>,
# log_nei_2008_pm10_sum_25000 <dbl>, popdens_county <dbl>,
# popdens_zcta <dbl>, nohs <dbl>, somehs <dbl>, hs <dbl>, somecollege <dbl>,
# associate <dbl>, bachelor <dbl>, grad <dbl>, pov <dbl>, hs_orless <dbl>,
# urc2013 <dbl>, urc2006 <dbl>, aod <dbl>
There were in contrast five monitors for the city of Baltimore, despite the fact that if we take a look at the land area and population of the counties for Blatimore City and Albuquerque, we can see that they had very similar land area and populations.
# A tibble: 5 x 2
county_area county_pop
<dbl> <dbl>
1 209643241 620961
2 209643241 620961
3 209643241 620961
4 209643241 620961
5 209643241 620961
# A tibble: 2 x 2
county_area county_pop
<dbl> <dbl>
1 3006530549 662564
2 3006530549 662564
In fact, the county containing Albuerque had a larger population. Thus the measurements for Albuquerque were not as thorough as they were for Baltimore.
This may be due to the fact that the monitor values were lower in Albuquerque. It is interesting to note here that the CMAQ values are quite similar for both cities.
Evaluate correlation
In prediction analyses, it is also useful to evaluate if any of the variables are correlated. Why should we care about this?
If we are using a linear regression to model our data then we might run into a problem called multicolinearity which can lead us to misinterpret what is really predictive of our outcome variable. This phenomenon occurs when the predictor variables actually predict one another. See this case study for a deeper explanation about this.
Another reason we should look out for correlation is that we don’t want to include redundant variables. This can add unnecessary noise to our algorithm causing a reduction in prediction accuracy and it can cause our algorithm to be unnecessarily slower. Finally, it can also make it difficult to interpret what variables are actually predictive.
Intuitively we can expect some of our variables to be correlated.
Let’s first take a look at all of our numeric variables with thecorrplot package: The corrplot package is another option to look at correlation among possible predictors, and particularly useful if we have many predictors.
First, we calculate the Pearson correlation coefficients between all features pairwise using the cor() function of the stats package (which is loaded automatically). Then we use the corrplot::corrplot() function.
The tl.cex = 0.5 argument controls the size of the text label.
We can also plot the absolute value of the Pearson correlation coefficients using the abs() function from base R and change the order of the columns.

There are several options for ordering the variables. See here for more options. Here we will use the “hclust” option for ordering by hierarchical clustering - which will order the variables by how similar they are to one another.
The cl.lim = c(0, 1) argument limits the color label to be between 0 and 1.
We can see that the development variables (imp) variables are correlated with each other as we might expect. We also see that the road density variables seem to be correlated with each other, and the emission variables seem to be correlated with each other.
Also notice that none of the predictors are highly correlated with our outcome variable (value).
We can take also take a closer look using the ggcorr() function and the ggpairs() function of the GGally package.
To select our variables of interest we can use the select() function with the contains() function of the tidyr package.
First let’s look at the imp/development variables. We can change the default color palette (palette = "RdBu") and add on correlation coefficients to the plot (label = TRUE).


Indeed, we can see that imp_a1000 and imp_a500 are highly correlated, as well as imp_a10000, imp_a15000.
Next, let’s take a look at the road density data:

We can see that many of the road density variables are highly correlated with one another, while others are less so.
Finally let’s look at the emission variables.


We would also expect the population density data might correlate with some of these variables. Let’s take a look.


Interesting, so these variables don’t appear to be highly correlated, therefore we might need variables from each of the categories to predict our monitor PM2.5 pollution values.
Because some variables in our data have extreme values, it might be good to take a log transformation. This can affect our estimates of correlation.


Indeed this increased the correlation, but variables from each of these categories may still prove to be useful for prediction.
Now that we have a sense of what our data are, we can get started with building a machine learning model to predict air pollution.
Data Visualization
Our main question for this case study was:
Can we predict annual average air pollution concentrations at the granularity of zip code regional levels using predictors such as data about population density, urbanization, road density, as well as, satellite pollution data and chemical modeling data?
Thus far, we have build a machine learning (ML) model to predict fine particulate matter air pollution levels based on our predictor variables (or features).
Now, let’s make a plot of our predicted outcome values (\(\hat{Y}\)) and actual outcome values \(Y\) we observed.
First, let’s start by making a plot of our monitors. To do this, we will use the following packages to create a map of the US:
sf - the simple features package helps to convert geographical coordinates into geometry variables which are useful for making 2D plots
maps - this package contains geographical outlines and plotting functions to create plots with maps
rnaturalearth- this allows for easy interaction with map data from Natural Earth which is a public domain map dataset
rgeos - this package interfaces with the Geometry Engine-Open Source (GEOS) which is also helpful for coordinate conversion
We will start with getting an outline of the US with the ne_countries() function of the rnaturalearth package which will return polygons of the countries in the Natural Earth dataset.
Rows: 241
Columns: 64
$ scalerank <int> 3, 1, 1, 1, 1, 3, 3, 1, 1, 1, 3, 1, 5, 3, 1, 1, 1, 1, 1, 1…
$ featurecla <chr> "Admin-0 country", "Admin-0 country", "Admin-0 country", "…
$ labelrank <dbl> 5, 3, 3, 6, 6, 6, 6, 4, 2, 6, 4, 4, 5, 6, 6, 2, 4, 5, 6, 2…
$ sovereignt <chr> "Netherlands", "Afghanistan", "Angola", "United Kingdom", …
$ sov_a3 <chr> "NL1", "AFG", "AGO", "GB1", "ALB", "FI1", "AND", "ARE", "A…
$ adm0_dif <dbl> 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0…
$ level <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ type <chr> "Country", "Sovereign country", "Sovereign country", "Depe…
$ admin <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ adm0_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ geou_dif <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ geounit <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ gu_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ su_dif <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ subunit <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ su_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ brk_diff <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ name <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ name_long <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ brk_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ brk_name <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ brk_group <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ abbrev <chr> "Aruba", "Afg.", "Ang.", "Ang.", "Alb.", "Aland", "And.", …
$ postal <chr> "AW", "AF", "AO", "AI", "AL", "AI", "AND", "AE", "AR", "AR…
$ formal_en <chr> "Aruba", "Islamic State of Afghanistan", "People's Republi…
$ formal_fr <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ note_adm0 <chr> "Neth.", NA, NA, "U.K.", NA, "Fin.", NA, NA, NA, NA, "U.S.…
$ note_brk <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "Multiple clai…
$ name_sort <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ name_alt <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ mapcolor7 <dbl> 4, 5, 3, 6, 1, 4, 1, 2, 3, 3, 4, 4, 1, 7, 2, 1, 3, 1, 2, 3…
$ mapcolor8 <dbl> 2, 6, 2, 6, 4, 1, 4, 1, 1, 1, 5, 5, 2, 5, 2, 2, 1, 6, 2, 2…
$ mapcolor9 <dbl> 2, 8, 6, 6, 1, 4, 1, 3, 3, 2, 1, 1, 2, 9, 5, 2, 3, 5, 5, 1…
$ mapcolor13 <dbl> 9, 7, 1, 3, 6, 6, 8, 3, 13, 10, 1, NA, 7, 11, 5, 7, 4, 8, …
$ pop_est <dbl> 103065, 28400000, 12799293, 14436, 3639453, 27153, 83888, …
$ gdp_md_est <dbl> 2258.0, 22270.0, 110300.0, 108.9, 21810.0, 1563.0, 3660.0,…
$ pop_year <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ lastcensus <dbl> 2010, 1979, 1970, NA, 2001, NA, 1989, 2010, 2010, 2001, 20…
$ gdp_year <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ economy <chr> "6. Developing region", "7. Least developed region", "7. L…
$ income_grp <chr> "2. High income: nonOECD", "5. Low income", "3. Upper midd…
$ wikipedia <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ fips_10 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ iso_a2 <chr> "AW", "AF", "AO", "AI", "AL", "AX", "AD", "AE", "AR", "AM"…
$ iso_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALA", "AND", "ARE", "A…
$ iso_n3 <chr> "533", "004", "024", "660", "008", "248", "020", "784", "0…
$ un_a3 <chr> "533", "004", "024", "660", "008", "248", "020", "784", "0…
$ wb_a2 <chr> "AW", "AF", "AO", NA, "AL", NA, "AD", "AE", "AR", "AM", "A…
$ wb_a3 <chr> "ABW", "AFG", "AGO", NA, "ALB", NA, "ADO", "ARE", "ARG", "…
$ woe_id <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ adm0_a3_is <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALA", "AND", "ARE", "A…
$ adm0_a3_us <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ adm0_a3_un <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ adm0_a3_wb <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ continent <chr> "North America", "Asia", "Africa", "North America", "Europ…
$ region_un <chr> "Americas", "Asia", "Africa", "Americas", "Europe", "Europ…
$ subregion <chr> "Caribbean", "Southern Asia", "Middle Africa", "Caribbean"…
$ region_wb <chr> "Latin America & Caribbean", "South Asia", "Sub-Saharan Af…
$ name_len <dbl> 5, 11, 6, 8, 7, 5, 7, 20, 9, 7, 14, 10, 23, 22, 17, 9, 7, …
$ long_len <dbl> 5, 11, 6, 8, 7, 13, 7, 20, 9, 7, 14, 10, 27, 35, 19, 9, 7,…
$ abbrev_len <dbl> 5, 4, 4, 4, 4, 5, 4, 6, 4, 4, 9, 4, 7, 10, 6, 4, 5, 4, 4, …
$ tiny <dbl> 4, NA, NA, NA, NA, 5, 5, NA, NA, NA, 3, NA, NA, 2, 4, NA, …
$ homepart <dbl> NA, 1, 1, NA, 1, NA, 1, 1, 1, 1, NA, 1, NA, NA, 1, 1, 1, 1…
$ geometry <MULTIPOLYGON [°]> MULTIPOLYGON (((-69.89912 1..., MULTIPOLYGON …
Here you can see the data about the countries in the world. Notice the geometry variable. This is used to create the outlines that we want.
Now we can use the geom_sf() function of the ggplot2 package to create a visual of simple feature (the geometry coordinates found in the geometry variable).

So now we can see that we have outlines of all the countries in the world.
We want to limit this just to the coordinates for the US. We will do this based on the coordinates we found on Wikipedia. According to this link, these are the latitude and longitude bounds of the continental US:
- top = 49.3457868 # north lat
- left = -124.7844079 # west long
- right = -66.9513812 # east long
- bottom = 24.7433195 # south lat
Now we just have a plot that is mostly limited to the outline of the US.
Now we will use the geom_point() function of the ggplot package to add scatter plot on top of the map. We want to show where the monitors are located based on the latitude and longitude values in the data.
Nice!
Now let’s add county lines.
County graphical data is available from the maps package. The sf package which again is short for simple features creates a data frame about this graphical data so that we can work with it.
Simple feature collection with 3076 features and 1 field
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -124.6813 ymin: 25.12993 xmax: -67.00742 ymax: 49.38323
CRS: EPSG:4326
First 10 features:
ID geom
1 alabama,autauga MULTIPOLYGON (((-86.50517 3...
2 alabama,baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama,barbour MULTIPOLYGON (((-85.42801 3...
4 alabama,bibb MULTIPOLYGON (((-87.02083 3...
5 alabama,blount MULTIPOLYGON (((-86.9578 33...
6 alabama,bullock MULTIPOLYGON (((-85.66866 3...
7 alabama,butler MULTIPOLYGON (((-86.8604 31...
8 alabama,calhoun MULTIPOLYGON (((-85.74313 3...
9 alabama,chambers MULTIPOLYGON (((-85.59416 3...
10 alabama,cherokee MULTIPOLYGON (((-85.46812 3...
Now we will use this data within the geom_sf() function to add this to our plot. We will also add a title using the ggtitle() function, as well as remove axis ticks and titles using the theme() function of the ggplot2 package.
monitors <- ggplot(data = world) +
geom_sf(data = counties, fill = NA, color = gray(.5))+
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE) +
geom_point(data = pm, aes(x = lon, y = lat), size = 2,
shape = 23, fill = "darkred") +
ggtitle("Monitor Locations") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
monitors

Great!
Now, let’s add a fill at the county-level for the true monitor values of air pollution.
First, we need to get the county map data that we just got and our air pollution data to have similarly formatted county names so that we can combine the datasets together.
We can see that in the county data the counties are listed after the state name and a comma. In addition they are all lower case.
Simple feature collection with 6 features and 1 field
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -88.01778 ymin: 30.24071 xmax: -85.06131 ymax: 34.2686
CRS: EPSG:4326
ID geom
1 alabama,autauga MULTIPOLYGON (((-86.50517 3...
2 alabama,baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama,barbour MULTIPOLYGON (((-85.42801 3...
4 alabama,bibb MULTIPOLYGON (((-87.02083 3...
5 alabama,blount MULTIPOLYGON (((-86.9578 33...
6 alabama,bullock MULTIPOLYGON (((-85.66866 3...
In contrast, our air pollution pm data shows counties as titles with the first letter as upper case.
[1] "Baldwin" "Clay" "Colbert" "DeKalb" "Etowah" "Houston"
We can use the separate() function of the tidyr package to separate the ID variable of our counties data into two variables based on the comma as a separator.
Simple feature collection with 6 features and 2 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -88.01778 ymin: 30.24071 xmax: -85.06131 ymax: 34.2686
CRS: EPSG:4326
state county geom
1 alabama autauga MULTIPOLYGON (((-86.50517 3...
2 alabama baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama barbour MULTIPOLYGON (((-85.42801 3...
4 alabama bibb MULTIPOLYGON (((-87.02083 3...
5 alabama blount MULTIPOLYGON (((-86.9578 33...
6 alabama bullock MULTIPOLYGON (((-85.66866 3...
Now we just need to make these names in the new county variable of the counties data to be in title format. We can use the str_to_title() function of the stringr package to do this.
Great! Now the county information is the same for the counties and pm data.
We can use the inner_join() function of the dplyr package to join the datasets together based on the county variables in each. This function will keep all rows that are in both datasets.
Rows: 3,926
Columns: 52
$ state.x <chr> "alabama", "alabama", "alabama", "alabama…
$ county <chr> "Baldwin", "Bibb", "Bibb", "Butler", "But…
$ id <fct> 1003.001, 13021.0007, 13021.0012, 39017.0…
$ value <dbl> 9.597647, 12.253134, 12.233673, 13.918079…
$ fips <fct> 1003, 13021, 13021, 39017, 39017, 13059, …
$ lat <dbl> 30.49800, 32.77746, 32.80541, 39.49380, 3…
$ lon <dbl> -87.88141, -83.64110, -83.54352, -84.3543…
$ state.y <chr> "Alabama", "Georgia", "Georgia", "Ohio", …
$ city <chr> "In a city", "In a city", "In a city", "I…
$ CMAQ <dbl> 8.098836, 11.716801, 11.716801, 11.321991…
$ zcta <fct> 36532, 31206, 31020, 45044, 45015, 30605,…
$ zcta_area <dbl> 190980522, 72325015, 276913325, 98746815,…
$ zcta_pop <dbl> 27829, 29072, 2541, 52822, 12038, 39952, …
$ imp_a500 <dbl> 0.01730104, 35.64359862, 0.28200692, 27.4…
$ imp_a1000 <dbl> 1.4096021, 24.4824827, 0.2973616, 28.2887…
$ imp_a5000 <dbl> 3.3360118, 8.7317283, 2.4691097, 22.69740…
$ imp_a10000 <dbl> 1.9879187, 9.1999720, 1.9873487, 11.90155…
$ imp_a15000 <dbl> 1.4386207, 6.4619966, 3.6435089, 8.405292…
$ county_area <dbl> 4117521611, 646879637, 646879637, 1209668…
$ county_pop <dbl> 182265, 155547, 155547, 368130, 368130, 1…
$ log_dist_to_prisec <dbl> 4.648181, 7.635438, 7.576493, 5.959728, 5…
$ log_pri_length_5000 <dbl> 8.517193, 10.215058, 10.659655, 9.747731,…
$ log_pri_length_10000 <dbl> 9.210340, 12.116408, 11.653566, 10.734382…
$ log_pri_length_15000 <dbl> 9.630228, 12.591833, 12.313347, 11.172817…
$ log_pri_length_25000 <dbl> 11.32735, 13.12475, 13.02383, 12.14238, 1…
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 6.214608, 8.104926, 7…
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 7.600902, 9.180109, 8…
$ log_prisec_length_5000 <dbl> 10.81504, 11.61283, 11.34202, 11.63677, 1…
$ log_prisec_length_10000 <dbl> 11.88680, 13.23991, 12.47152, 12.62117, 1…
$ log_prisec_length_15000 <dbl> 12.20572, 13.74532, 13.37704, 13.26170, 1…
$ log_prisec_length_25000 <dbl> 13.41395, 14.28483, 14.25295, 14.16745, 1…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.3180354, 5.5380414, 0.1972941, 7.230784…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967359, 5.538041, 5.536822, 7.408732, 5…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 5.986616, 5.986572, 7.538614, 7…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.3558851, 5.6035407, 0.9849611, 7.278576…
$ log_nei_2008_pm10_sum_15000 <dbl> 2.2678341, 5.6035407, 5.5971561, 7.489928…
$ log_nei_2008_pm10_sum_25000 <dbl> 5.6287284, 6.0302900, 6.0347672, 7.633004…
$ popdens_county <dbl> 44.265706, 240.457407, 240.457407, 304.32…
$ popdens_zcta <dbl> 145.716431, 401.963277, 9.176156, 534.923…
$ nohs <dbl> 3.300, 8.700, 6.800, 1.300, 3.500, 3.800,…
$ somehs <dbl> 4.900, 24.700, 17.500, 3.300, 7.700, 6.80…
$ hs <dbl> 25.10, 32.60, 46.60, 33.40, 33.40, 17.80,…
$ somecollege <dbl> 19.7, 12.9, 18.7, 23.0, 23.2, 16.1, 18.8,…
$ associate <dbl> 8.200, 4.800, 5.000, 8.700, 8.100, 5.100,…
$ bachelor <dbl> 25.30, 8.90, 4.00, 22.20, 16.20, 25.40, 5…
$ grad <dbl> 13.50, 7.30, 1.30, 8.10, 7.90, 25.00, 3.1…
$ pov <dbl> 6.100, 38.800, 26.800, 0.900, 6.900, 12.1…
$ hs_orless <dbl> 33.30, 66.00, 70.90, 38.00, 44.60, 28.40,…
$ urc2013 <dbl> 4, 4, 4, 2, 2, 4, 6, 2, 4, 1, 1, 1, 3, 4,…
$ urc2006 <dbl> 5, 4, 4, 2, 2, 4, 6, 2, 4, 1, 1, 1, 3, 4,…
$ aod <dbl> 37.36364, 36.25000, 30.45455, 48.36364, 5…
$ geom <MULTIPOLYGON [°]> MULTIPOLYGON (((-87.93757 3.…
Nice! we can see that we have add a geom variable to the pm data.
Now we can use this to color the counties in our plot based on the value variable of our pm data, which you may recall is the actual monitor data for fine particulate air pollution at each monitor.
WE can do so using the scale_fill_gradientn() function of the ggplot2 package which creates color gradient based on a variable. In this case it is the variable that was specified as the fill in the aes function of the geom_sf() function. We specified that it would be the value variable of the pm data.
This scale_fill_gradientn() function also allows you to specify the colors, what to do about NA values (should they be a specific color or transparent) and the breaks, limits, labels and name/title on the legend for the color gradient.
truth <-ggplot(data = world) +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50), expand = FALSE)+
geom_sf(data = map_data, aes(fill = value)) +
scale_fill_gradientn(colours=topo.colors(7), na.value = "transparent",
breaks=c(0,10,20),labels=c(0,10,20),
limits=c(0,23.5), name = "PM ug/m3") +
ggtitle("True PM 2.5 levels") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
truth
Nice!
Now let’s do the same with our predicted outcome values.
Let’s grab both the testing and training predicted outcome values so that we have as much data as possible.
First we need to fit our training data with our final model to be able to get the predictions for the monitors included in the training set. We did this using the last_fit() function, but the output of this makes it difficult to grab the predicted values for the training data, and it is also difficult to get the id variables for the testing data.
Thus we will use the parsnip fit() and predict() functions of the parsnip package to do this like so:
Question Opportunity
Why do we not need pre-processed data?
Click here to reveal the answer.
Since we are using a workflow, the data will be pre-processed when it is fit as well.
# A tibble: 584 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 10.0 9.60 1003 Baldwin 1003.001
2 11.0 10.8 1027 Clay 1027.0001
3 11.5 11.2 1033 Colbert 1033.1002
4 12.0 12.4 1055 Etowah 1055.001
5 10.8 10.5 1069 Houston 1069.0003
6 14.5 15.6 1073 Jefferson 1073.0023
7 12.1 12.4 1073 Jefferson 1073.1005
8 11.0 11.1 1073 Jefferson 1073.1009
9 13.9 14.6 1073 Jefferson 1073.2003
10 11.8 12.0 1073 Jefferson 1073.5002
# … with 574 more rows
# A tibble: 292 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 11.7 11.7 1049 DeKalb 1049.1003
2 12.6 13.1 1073 Jefferson 1073.101
3 12.3 12.2 1073 Jefferson 1073.2006
4 12.0 12.2 1089 Madison 1089.0014
5 11.5 11.4 1103 Morgan 1103.0011
6 12.4 12.2 1121 Talladega 1121.0002
7 10.8 10.9 4013 Maricopa 4013.4003
8 10.4 10.6 4021 Pinal 4021.0001
9 12.0 14.1 4023 Santa Cruz 4023.0004
10 7.69 5.83 4025 Yavapai 4025.2002
# … with 282 more rows
Now we can combine this data for the predictions for all monitors using the bind_rows() function of the dplyr package, which will essentially append the second dataset to the first.
# A tibble: 876 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 11.7 11.7 1049 DeKalb 1049.1003
2 12.6 13.1 1073 Jefferson 1073.101
3 12.3 12.2 1073 Jefferson 1073.2006
4 12.0 12.2 1089 Madison 1089.0014
5 11.5 11.4 1103 Morgan 1103.0011
6 12.4 12.2 1121 Talladega 1121.0002
7 10.8 10.9 4013 Maricopa 4013.4003
8 10.4 10.6 4021 Pinal 4021.0001
9 12.0 14.1 4023 Santa Cruz 4023.0004
10 7.69 5.83 4025 Yavapai 4025.2002
# … with 866 more rows
Great! as we can see there are 876 values like we would expect for all of the monitors. We can use the county variable to combine this with the counties data like we did with the pm data previously so that we can use the value variable as a color scheme for our map.
map_data <- inner_join(counties, all_pred, by = "county")
pred <- ggplot(data = world) +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE) +
geom_sf(data = map_data, aes(fill = .pred)) +
scale_fill_gradientn(colours=topo.colors(7), na.value = "transparent",
breaks=c(0,10,20),labels=c(0,10,20),
limits=c(0,23.5), name = "PM ug/m3") +
ggtitle("Predicted PM 2.5 levels")+
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
pred

Now we will use the patchwork package to combine our last two plots. This allows us to combine plots using the + or the / . The + will place plots side by side and the / will place plots top to bottom.
Now let’s just combine the truth plot and the prediction plots together:

We can see that the predicted fine particle air pollution values in (ug/m3) are quite similar to the true values measured by the actual gravimetric monitors. We can also see that southern California has some large counties with worse pollution (as they are yellow and thus have much higher particulate matter levels).
Let’s add some text to our plot to explain it a bit more. We can do so using the plot_annotation() function of the patchwork package. The theme argument of this function takes the same theme information using the theme() function of the ggplot2 package as when creating ggplot2plots.

LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXM6IFByZWRpY3RpbmcgQW5udWFsIEFpciBQb2xsdXRpb24iCmNzczogc3R5bGUuY3NzCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgc2VsZl9jb250YWluZWQ6IHllcwogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vCiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogeWVzCgotLS0KPHN0eWxlPgojVE9DIHsKICBiYWNrZ3JvdW5kOiB1cmwoImh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pby9pbWcvbG9nby5qcGciKTsKICBiYWNrZ3JvdW5kLXNpemU6IGNvbnRhaW47CiAgcGFkZGluZy10b3A6IDI0MHB4ICFpbXBvcnRhbnQ7CiAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDsKfQo8L3N0eWxlPgoKPCEtLSBPcGVuIGFsbCBsaW5rcyBpbiBuZXcgdGFiLS0+ICAKPGJhc2UgdGFyZ2V0PSJfYmxhbmsiLz4gCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShrbml0cikKbGlicmFyeShoZXJlKQprbml0cjo6b3B0c19jaHVuayRzZXQoaW5jbHVkZSA9IFRSVUUsIGNvbW1lbnQgPSBOQSwgZWNobyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgY2FjaGUgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiLCBvdXQud2lkdGggPSAnOTAlJykKYGBgCgoKIyMjIyB7Lm91dGxpbmUgfQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiODAwIHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgIm1haW5fcGxvdF9tYXBzLnBuZyIpKQpgYGAKCiMjIyMKCiMjIyMgey5kaXNjbGFpbWVyX2Jsb2NrfQoKKipEaXNjbGFpbWVyKio6IFRoZSBwdXJwb3NlIG9mIHRoZSBbT3BlbiBDYXNlIFN0dWRpZXNdKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pbyl7dGFyZ2V0PSJfYmxhbmsifSBwcm9qZWN0IGlzICoqdG8gZGVtb25zdHJhdGUgdGhlIHVzZSBvZiB2YXJpb3VzIGRhdGEgc2NpZW5jZSBtZXRob2RzLCB0b29scywgYW5kIHNvZnR3YXJlIGluIHRoZSBjb250ZXh0IG9mIG1lc3N5LCByZWFsLXdvcmxkIGRhdGEqKi4gQSBnaXZlbiBjYXNlIHN0dWR5IGRvZXMgbm90IGNvdmVyIGFsbCBhc3BlY3RzIG9mIHRoZSByZXNlYXJjaCBwcm9jZXNzLCBpcyBub3QgY2xhaW1pbmcgdG8gYmUgdGhlIG1vc3QgYXBwcm9wcmlhdGUgd2F5IHRvIGFuYWx5emUgYSBnaXZlbiBkYXRhIHNldCwgYW5kIHNob3VsZCBub3QgYmUgdXNlZCBpbiB0aGUgY29udGV4dCBvZiBtYWtpbmcgcG9saWN5IGRlY2lzaW9ucyB3aXRob3V0IGV4dGVybmFsIGNvbnN1bHRhdGlvbiBmcm9tIHNjaWVudGlmaWMgZXhwZXJ0cy4gCgojIyMjCgojIyMjIHsubGljZW5zZV9ibG9ja30KClRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciB0aGUgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBbKENDIEJZLU5DIDMuMCldKGh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvdXMvKXt0YXJnZXQ9Il9ibGFuayJ9IFVuaXRlZCBTdGF0ZXMgTGljZW5zZS4KCiMjIyMKCiMjIyMgey5yZWZlcmVuY2VfYmxvY2t9CgpUbyBjaXRlIHRoaXMgY2FzZSBzdHVkeSBwbGVhc2UgdXNlOgoKV3JpZ2h0LCBDYXJyaWUgYW5kIEphZ2VyLCBMZWFoIGFuZCBUYXViLCBNYXJnYXJldCBhbmQgSGlja3MsIFN0ZXBoYW5pZS4gKDIwMjApLiBbaHR0cHM6Ly93d3cub3BlbmNhc2VzdHVkaWVzLm9yZy9vY3MtYnAtYWlyLXBvbGx1dGlvbi9dKGh0dHBzOi8vd3d3Lm9wZW5jYXNlc3R1ZGllcy5vcmcvb2NzLWJwLWFpci1wb2xsdXRpb24vKS4gUHJlZGljdGluZyBBbm51YWwgQWlyIFBvbGx1dGlvbiAoVmVyc2lvbiB2MS4wLjApLgoKIyMjIwoKIyAqKk1vdGl2YXRpb24qKgoqKioKQSB2YXJpZXR5IG9mIGRpZmZlcmVudCBzb3VyY2VzIGNvbnRyaWJ1dGUgZGlmZmVyZW50IHR5cGVzIG9mIHBvbGx1dGFudHMgdG8gd2hhdCB3ZSBjYWxsIGFpciBwb2xsdXRpb24uIAoKU29tZSBzb3VyY2VzIGFyZSBuYXR1cmFsIHdoaWxlIG90aGVycyBhcmUgYW50aHJvcG9nZW5pYyAoaHVtYW4gZGVyaXZlZCk6Cgo8cCBhbGlnbj0iY2VudGVyIj4KPGltZyB3aWR0aD0iNjAwIiBzcmM9Imh0dHBzOi8vd3d3Lm5wcy5nb3Yvc3ViamVjdHMvYWlyL2ltYWdlcy9Tb3VyY2VzX0dyYXBoaWNfSHVnZS5qcGc/bWF4d2lkdGg9MTIwMCZtYXhoZWlnaHQ9MTIwMCZhdXRvcm90YXRlPWZhbHNlIj4KPC9wPgoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5nb29nbGUuY29tL3VybD9zYT1pJnVybD1odHRwcyUzQSUyRiUyRnd3dy5ucHMuZ292JTJGc3ViamVjdHMlMkZhaXIlMkZzb3VyY2VzLmh0bSZwc2lnPUFPdlZhdzJ2N0FWeFNGOFpTQVBFaE51ZFZ0Yk4mdXN0PTE1ODU3NzA5NjYyMTcwMDAmc291cmNlPWltYWdlcyZjZD12ZmUmdmVkPTBDQUlRalJ4cUZ3b1RDUERONjZxX3hlZ0NGUUFBQUFBZEFBQUFBQkFEKXt0YXJnZXQ9Il9ibGFuayJ9CgojIyMgTWFqb3IgdHlwZXMgb2YgYWlyIHBvbGx1dGFudHMKCjEpICoqR2FzZW91cyoqIC0gQ2FyYm9uIE1vbm94aWRlIChDTyksIE96b25lIChPfjN+KSwgTml0cm9nZW4gT3hpZGVzKE5PLCBOT34yfiksIFN1bHBoZXIgRGlveGlkZSAoU09+Mn4pCjIpICoqUGFydGljdWxhdGUqKiAtIHNtYWxsIGxpcXVpZHMgYW5kIHNvbGlkcyBzdXNwZW5kZWQgaW4gdGhlIGFpciAoaW5jbHVkZXMgbGVhZC0gY2FuIGluY2x1ZGUgY2VydGFpbiB0eXBlcyBvZiBkdXN0KQozKSAqKkR1c3QqKiAtIHNtYWxsIHNvbGlkcyAobGFyZ2VyIHRoYW4gcGFydGljdWxhdGVzKSB0aGF0IGNhbiBiZSBzdXNwZW5kZWQgaW4gdGhlIGFpciBmb3Igc29tZSB0aW1lIGJ1dCBldmVudHVhbGx5IHNldHRsZQo0KSAqKkJpb2xvZ2ljYWwqKiAtIHBvbGxlbiwgYmFjdGVyaWEsIHZpcnVzZXMsIG1vbGQgc3BvcmVzCgpTZWUgW2hlcmVdKGh0dHA6Ly93d3cucmVkbG9nZW52LmNvbS93b3JrZXItc2FmZXR5L3BhcnQtMS1kdXN0LWFuZC1wYXJ0aWN1bGF0ZS1tYXR0ZXIpIGZvciBtb3JlIGRldGFpbCBvbiB0aGUgdHlwZXMgb2YgcG9sbHV0YW50cyBpbiB0aGUgYWlyLgoKCiMjIyBQYXJ0aWN1bGF0ZSBwb2xsdXRpb24gCgpBaXIgcG9sbHV0aW9uIHBhcnRpY3VsYXRlcyBhcmUgZ2VuZXJhbGx5IGRlc2NyaWJlZCBieSB0aGVpciAqKnNpemUqKi4KClRoZXJlIGFyZSAzIG1ham9yIGNhdGVnb3JpZXM6CgoxKSAqKkxhcmdlIENvYXJzZSoqIFBhcnRpY3VsYXRlIE1hdHRlciAtIGhhcyBkaWFtZXRlciBvZiA+MTAgbWljcm9tZXRlcnMgKDEwIMK1bSkgCgoyKSAqKkNvYXJzZSoqIFBhcnRpY3VsYXRlIE1hdHRlciAoY2FsbGVkICoqUE1+MTAtMi41fioqKSAtIGhhcyBkaWFtZXRlciBvZiBiZXR3ZWVuIDIuNSDCtW0gYW5kIDEwIMK1bQoKMykgKipGaW5lKiogUGFydGljdWxhdGUgTWF0dGVyIChjYWxsZWQgKipQTX4yLjV+KiopIC0gaGFzIGRpYW1ldGVyIG9mIDwgMi41IMK1bSAKCioqUE1+MTB+KiogaW5jbHVkZXMgYW55IHBhcnRpY3VsYXRlIG1hdHRlciA8MTAgwrVtIChib3RoIGNvYXJzZSBhbmQgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIpCgpIZXJlIHlvdSBjYW4gc2VlIGhvdyB0aGVzZSBzaXplcyBjb21wYXJlIHdpdGggYSBodW1hbiBoYWlyOgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSAiNjAwIHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInBtMi41X3NjYWxlX2dyYXBoaWMtY29sb3JfMi5qcGciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmVwYS5nb3YvcG0tcG9sbHV0aW9uL3BhcnRpY3VsYXRlLW1hdHRlci1wbS1iYXNpY3Mpe3RhcmdldD0iX2JsYW5rIn0KCjwhLS0gPHAgYWxpZ249ImNlbnRlciI+IC0tPgo8IS0tICAgPGltZyB3aWR0aD0iNTAwIiBzcmM9Imh0dHBzOi8vd3d3LnNlbnNpcmlvbi5jb20vaW1hZ2VzL3NlbnNpcmlvbi1zcGVjaWFsaXN0LWFydGljbGUtZmlndXJlLTEtY2RkNzAuanBnIj4gLS0+CjwhLS0gPC9wPiAtLT4KCgo8dT5UaGUgZm9sbG93aW5nIHBsb3QgYW5kIHRhYmxlIHNob3cgdGhlIHJlbGF0aXZlIHNpemVzIG9mIHRoZXNlIGRpZmZlcmVudCBwb2xsdXRhbnRzIGluIG1pY3JvbWV0ZXJzICjCtW0pOjwvdT4KCjxwIGFsaWduPSJjZW50ZXIiPgogIDxpbWcgd2lkdGg9IjYwMCIgc3JjPSJodHRwczovL3VwbG9hZC53aWtpbWVkaWEub3JnL3dpa2lwZWRpYS9jb21tb25zL3RodW1iL2QvZGYvQWlyYm9ybmUtcGFydGljdWxhdGUtc2l6ZS1jaGFydC5zdmcvODAwcHgtQWlyYm9ybmUtcGFydGljdWxhdGUtc2l6ZS1jaGFydC5zdmcucG5nIj4KPC9wPgoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9QYXJ0aWN1bGF0ZXMpe3RhcmdldD0iX2JsYW5rIn0KCgo8cCBhbGlnbj0iY2VudGVyIj4KICA8aW1nIHdpZHRoPSI1MDAiIHNyYz0iaHR0cHM6Ly93d3cuZnJvbnRpZXJzaW4ub3JnL2ZpbGVzL0FydGljbGVzLzUwNTU3MC9mcHViaC0wOC0wMDAxNC1IVE1ML2ltYWdlX20vZnB1YmgtMDgtMDAwMTQtdDAwMi5qcGciPgo8L3A+CgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmZyb250aWVyc2luLm9yZy9hcnRpY2xlcy8xMC4zMzg5L2ZwdWJoLjIwMjAuMDAwMTQvZnVsbCl7dGFyZ2V0PSJfYmxhbmsifQoKCjx1PlRoaXMgdGFibGUgc2hvd3MgaG93IGRlZXBseSBzb21lIG9mIHRoZSBzbWFsbGVyIGZpbmUgcGFydGljbGVzIGNhbiBwZW5ldHJhdGUgd2l0aGluIHRoZSBodW1hbiBib2R5OjwvdT4KCjxwIGFsaWduPSJjZW50ZXIiPgogIDxpbWcgd2lkdGg9IjUwMCIgc3JjPSJodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvZmlsZXMvQXJ0aWNsZXMvNTA1NTcwL2ZwdWJoLTA4LTAwMDE0LUhUTUwvaW1hZ2VfbS9mcHViaC0wOC0wMDAxNC10MDAxLmpwZyI+CjwvcD4KCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuZnJvbnRpZXJzaW4ub3JnL2FydGljbGVzLzEwLjMzODkvZnB1YmguMjAyMC4wMDAxNC9mdWxsKXt0YXJnZXQ9Il9ibGFuayJ9CgoKIyMjIE5lZ2F0aXZlIGltcGFjdCBvZiBwYXJ0aWN1bGF0ZSBleHBvc3VyZSBvbiBoZWFsdGggCgpFeHBvc3VyZSB0byBhaXIgcG9sbHV0aW9uIGlzIGFzc29jaWF0ZWQgd2l0aCBoaWdoZXIgcmF0ZXMgb2YgW21vcnRhbGl0eV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DNTc4MzE4Ni8pe3RhcmdldD0iX2JsYW5rIn0gaW4gb2xkZXIgYWR1bHRzIGFuZCBpcyBrbm93biB0byBiZSBhIHJpc2sgZmFjdG9yIGZvciBtYW55IGRpc2Vhc2VzIGFuZCBjb25kaXRpb25zIGluY2x1ZGluZyBidXQgbm90IGxpbWl0ZWQgdG86CgoxKSBbQXN0aG1hXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8yOTI0MzkzNyl7dGFyZ2V0PSJfYmxhbmsifSAtIGZpbmUgcGFydGljbGUgZXhwb3N1cmUgKCoqUE1+Mi41fioqKSB3YXMgZm91bmQgdG8gYmUgYXNzb2NpYXRlZCB3aXRoIGhpZ2hlciByYXRlcyBvZiBhc3RobWEgaW4gY2hpbGRyZW4KMikgW0luZmxhbW1hdGlvbiBpbiB0eXBlIDEgZGlhYmV0ZXNdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHVibWVkLzMxNDE5NzY1KXt0YXJnZXQ9Il9ibGFuayJ9IC0gZmluZSBwYXJ0aWNsZSBleHBvc3VyZSAoKipQTX4yLjV+KiopIGZyb20gdHJhZmZpYy1yZWxhdGVkIGFpciBwb2xsdXRpb24gd2FzIGFzc29jaWF0ZWQgd2l0aCBpbmNyZWFzZWQgbWVhc3VyZXMgb2YgaW5mbGFtbWF0b3J5IG1hcmtlcnMgaW4geW91dGhzIHdpdGggVHlwZSAxIGRpYWJldGVzCjMpIFtMdW5nIGZ1bmN0aW9uIGFuZCBlbXBoeXNlbWFdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHVibWVkLzMxNDA4MTM1KXt0YXJnZXQ9Il9ibGFuayJ9IC0gaGlnaGVyIGNvbmNlbnRyYXRpb25zIG9mIG96b25lIChPfjN+KSwgbml0cm9nZW4gb3hpZGVzIChOT354fiksIGJsYWNrIGNhcmJvbiwgYW5kIGZpbmUgcGFydGljbGUgZXhwb3N1cmUgKipQTX4yLjV+KiogLCBhdCBzdHVkeSBiYXNlbGluZSB3ZXJlIHNpZ25pZmljYW50bHkgYXNzb2NpYXRlZCB3aXRoIGdyZWF0ZXIgaW5jcmVhc2VzIGluIHBlcmNlbnQgZW1waHlzZW1hIHBlciAxMCB5ZWFycyAKNCkgW0xvdyBiaXJ0aHdlaWdodF0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMzEzODY2NDMpe3RhcmdldD0iX2JsYW5rIn0gLSBmaW5lIHBhcnRpY2xlIGV4cG9zdXJlKCoqUE1+Mi41fioqKSB3YXMgYXNzb2NpYXRlZCB3aXRoIGxvd2VyIGJpcnRoIHdlaWdodCBpbiBmdWxsLXRlcm0gbGl2ZSBiaXJ0aHMKNSkgW1ZpcmFsIEluZmVjdGlvbl0oaHR0cHM6Ly93d3cudGFuZGZvbmxpbmUuY29tL2RvaS9mdWxsLzEwLjEwODAvMDg5NTgzNzA3MDE2NjU0MzQpe3RhcmdldD0iX2JsYW5rIn0gLSBoaWdoZXIgcmF0ZXMgb2YgaW5mZWN0aW9uIGFuZCBpbmNyZWFzZWQgc2V2ZXJpdHkgb2YgaW5mZWN0aW9uIGFyZSBhc3NvY2lhdGVkIHdpdGggaGlnaGVyIGV4cG9zdXJlcyB0byBwb2xsdXRpb24gbGV2ZWxzIGluY2x1ZGluZyBmaW5lIHBhcnRpY2xlIGV4cG9zdXJlICgqKlBNfjIuNX4qKikKClNlZSB0aGlzIFtyZXZpZXcgYXJ0aWNsZV0oaHR0cHM6Ly93d3cuZnJvbnRpZXJzaW4ub3JnL2FydGljbGVzLzEwLjMzODkvZnB1YmguMjAyMC4wMDAxNC9mdWxsKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IHNvdXJjZXMgb2YgYWlyIHBvbGx1dGlvbiBhbmQgdGhlIGluZmx1ZW5jZSBvZiBhaXIgcG9sbHV0aW9uIG9uIGhlYWx0aC4KCiMjIyBTcGFyc2UgbW9uaXRvcmluZyBpcyBwcm9ibGVtYXRpYyBmb3IgUHVibGljIEhlYWx0aAoKSGlzdG9yaWNhbGx5LCBlcGlkZW1pb2xvZ2ljYWwgc3R1ZGllcyB3b3VsZCBhc3Nlc3MgdGhlIGluZmx1ZW5jZSBvZiBhaXIgcG9sbHV0aW9uIG9uIGhlYWx0aCBvdXRjb21lcyBieSByZWx5aW5nIG9uIGEgbnVtYmVyIG9mIG1vbml0b3JzIGxvY2F0ZWQgYXJvdW5kIHRoZSBjb3VudHJ5LiAKCkhvd2V2ZXIsIGFzIGNhbiBiZSBzZWVuIGluIHRoZSBmb2xsb3dpbmcgZmlndXJlLCB0aGVzZSBtb25pdG9ycyBhcmUgcmVsYXRpdmVseSBzcGFyc2UgaW4gY2VydGFpbiByZWdpb25zIG9mIHRoZSBjb3VudHJ5IGFuZCBhcmUgbm90IG5lY2Vzc2FyaWx5IGxvY2F0ZWQgbmVhciBwb2xsdXRpb24gc291cmNlcy4gV2Ugd2lsbCBzZWUgbGF0ZXIgd2hlbiB3ZSBldmFsdWF0ZSB0aGUgZGF0YSwgdGhhdCBldmVuIGluIGNlcnRhaW4gcmVsYXRpdmVseSBsYXJnZSBjaXRpZXMgdGhlcmUgaXMgb25seSAgb25lIG1vbml0b3IhCgpGdXJ0aGVybW9yZSwgZHJhbWF0aWMgZGlmZmVyZW5jZXMgaW4gcG9sbHV0aW9uIHJhdGVzIGNhbiBiZSBzZWVuIGV2ZW4gd2l0aGluIHRoZSBzYW1lIGNpdHkuIEluIGZhY3QsIHRoZSB0ZXJtIG1pY3JvLWVudmlyb25tZW50cyBkZXNjcmliZXMgZW52aXJvbm1lbnQgd2l0aGluIGNpdGllcyBvciBjb3VudGllcyB3aGljaCBtYXkgdmFyeSBncmVhdGx5IGZyb20gb25lIGJsb2NrIHRvIGFub3RoZXIuCgo8cCBhbGlnbj0iY2VudGVyIj4KICA8aW1nIHdpZHRoPSI0MDAiIHNyYz0iaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DNDEzNzI3Mi9iaW4vMTQ3Ni0wNjlYLTEzLTYzLTEuanBnIj4KPC9wPgoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL2Voam91cm5hbC5iaW9tZWRjZW50cmFsLmNvbS9hcnRpY2xlcy8xMC4xMTg2LzE0NzYtMDY5WC0xMy02Myl7dGFyZ2V0PSJfYmxhbmsifQoKVGhpcyBsYWNrIG9mIGdyYW51bGFyaXR5IGluIGFpciBwb2xsdXRpb24gbW9uaXRvcmluZyBoYXMgaGluZGVyZWQgb3VyIGFiaWxpdHkgdG8gZGlzY2VybiB0aGUgZnVsbCBpbXBhY3Qgb2YgYWlyIHBvbGx1dGlvbiBvbiBoZWFsdGggYW5kIHRvIGlkZW50aWZ5IGF0LXJpc2sgbG9jYXRpb25zLiAKCgojIyMgTWFjaGluZSBsZWFybmluZyBvZmZlcnMgYSBzb2x1dGlvbgoKQW4gW2FydGljbGVdKGh0dHBzOi8vZWhqb3VybmFsLmJpb21lZGNlbnRyYWwuY29tL2FydGljbGVzLzEwLjExODYvMTQ3Ni0wNjlYLTEzLTYzKXt0YXJnZXQ9Il9ibGFuayJ9IHB1Ymxpc2hlZCBpbiB0aGUgKkVudmlyb25tZW50YWwgSGVhbHRoKiBqb3VybmFsIGRlYWx0IHdpdGggdGhpcyBpc3N1ZSBieSB1c2luZyBkYXRhLCBpbmNsdWRpbmcgcG9wdWxhdGlvbiBkZW5zaXR5LCByb2FkIGRlbnNpdHksIGFtb25nIG90aGVyIGZlYXR1cmVzLCB0byBtb2RlbCBvciBwcmVkaWN0IGFpciBwb2xsdXRpb24gbGV2ZWxzIGF0IGEgbW9yZSBsb2NhbGl6ZWQgc2NhbGUgdXNpbmcgbWFjaGluZSBsZWFybmluZyAoTUwpIG1ldGhvZHMuIAoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSAiODAwIHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInRoZXBhcGVyLnBuZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9laGpvdXJuYWwuYmlvbWVkY2VudHJhbC5jb20vYXJ0aWNsZXMvMTAuMTE4Ni8xNDc2LTA2OVgtMTMtNjMpe3RhcmdldD0iX2JsYW5rIn0KCiMjIyMgey5yZWZlcmVuY2VfYmxvY2t9Cllhbm9za3ksIEouIEQuIGV0IGFsLiBTcGF0aW8tdGVtcG9yYWwgbW9kZWxpbmcgb2YgcGFydGljdWxhdGUgYWlyIHBvbGx1dGlvbiBpbiB0aGUgY29udGVybWlub3VzIFVuaXRlZCBTdGF0ZXMgdXNpbmcgZ2VvZ3JhcGhpYyBhbmQgbWV0ZW9yb2xvZ2ljYWwgcHJlZGljdG9ycy4gKkVudmlyb24gSGVhbHRoKiAxMywgNjMgKDIwMTQpLgoKIyMjIwoKVGhlIGF1dGhvcnMgb2YgdGhpcyBhcnRpY2xlIHN0YXRlIHRoYXQ6Cgo+ICJFeHBvc3VyZSB0byBhdG1vc3BoZXJpYyBwYXJ0aWN1bGF0ZSBtYXR0ZXIgKFBNKSByZW1haW5zIGFuIGltcG9ydGFudCBwdWJsaWMgaGVhbHRoIGNvbmNlcm4sIGFsdGhvdWdoIGl0IHJlbWFpbnMgZGlmZmljdWx0IHRvIHF1YW50aWZ5IGFjY3VyYXRlbHkgYWNyb3NzIGxhcmdlIGdlb2dyYXBoaWMgYXJlYXMgd2l0aCBzdWZmaWNpZW50bHkgaGlnaCBzcGF0aWFsIHJlc29sdXRpb24uIFJlY2VudCBlcGlkZW1pb2xvZ2ljIGFuYWx5c2VzIGhhdmUgZGVtb25zdHJhdGVkIHRoZSBpbXBvcnRhbmNlIG9mIHNwYXRpYWxseS0gYW5kIHRlbXBvcmFsbHktcmVzb2x2ZWQgZXhwb3N1cmUgZXN0aW1hdGVzLCB3aGljaCBzaG93IGxhcmdlciBQTS1tZWRpYXRlZCBoZWFsdGggZWZmZWN0cyBhcyBjb21wYXJlZCB0byBuZWFyZXN0IG1vbml0b3Igb3IgY291bnR5LXNwZWNpZmljIGFtYmllbnQgY29uY2VudHJhdGlvbnMuIiAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9laGpvdXJuYWwuYmlvbWVkY2VudHJhbC5jb20vYXJ0aWNsZXMvMTAuMTE4Ni8xNDc2LTA2OVgtMTMtNjMpe3RhcmdldD0iX2JsYW5rIn0KClRoZSBhcnRpY2xlIGFib3ZlIGRlbW9uc3RyYXRlcyB0aGF0IG1hY2hpbmUgbGVhcm5pbmcgbWV0aG9kcyBjYW4gYmUgdXNlZCB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24gbGV2ZWxzIHdoZW4gdHJhZGl0aW9uYWwgbW9uaXRvcmluZyBzeXN0ZW1zIGFyZSBub3QgYXZhaWxhYmxlIGluIGEgcGFydGljdWxhciBhcmVhIG9yIHdoZW4gdGhlcmUgaXMgbm90IGVub3VnaCBzcGF0aWFsIGdyYW51bGFyaXR5IHdpdGggY3VycmVudCBtb25pdG9yaW5nIHN5c3RlbXMuIApXZSB3aWxsIHVzZSBzaW1pbGFyIG1ldGhvZHMgdG8gcHJlZGljdCBhbm51YWwgYWlyIHBvbGx1dGlvbiBsZXZlbHMgc3BhdGlhbGx5IHdpdGhpbiB0aGUgVVMuCgoKIyAqKk1haW4gUXVlc3Rpb24qKgoqKioKCiMjIyMgey5tYWluX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gT3VyIG1haW4gcXVlc3Rpb246IDwvdT48L2I+CgoxKSBDYW4gd2UgcHJlZGljdCBhbm51YWwgYXZlcmFnZSBhaXIgcG9sbHV0aW9uIGNvbmNlbnRyYXRpb25zIGF0IHRoZSBncmFudWxhcml0eSBvZiB6aXAgY29kZSByZWdpb25hbCBsZXZlbHMgdXNpbmcgcHJlZGljdG9ycyBzdWNoIGFzIGRhdGEgYWJvdXQgcG9wdWxhdGlvbiBkZW5zaXR5LCB1cmJhbml6YXRpb24sIHJvYWQgZGVuc2l0eSwgYXMgd2VsbCBhcywgc2F0ZWxsaXRlIHBvbGx1dGlvbiBkYXRhIGFuZCBjaGVtaWNhbCBtb2RlbGluZyBkYXRhPwoKIyMjIwoKIyAqKkxlYXJuaW5nIE9iamVjdGl2ZXMqKgoqKioKCkluIHRoaXMgY2FzZSBzdHVkeSwgd2Ugd2lsbCB3YWxrIHlvdSB0aHJvdWdoIGltcG9ydGluZyBkYXRhIGZyb20gQ1NWIGZpbGVzIGFuZCBwZXJmb3JtaW5nIG1hY2hpbmUgbGVhcm5pbmcgbWV0aG9kcyB0byBwcmVkaWN0IG91ciBvdXRjb21lIHZhcmlhYmxlIG9mIGludGVyZXN0IChpbiB0aGlzIGNhc2UgYW5udWFsIGZpbmUgcGFydGljbGUgYWlyIHBvbGx1dGlvbiBlc3RpbWF0ZXMpLiAKCldlIHdpbGwgZXNwZWNpYWxseSBmb2N1cyBvbiB1c2luZyBwYWNrYWdlcyBhbmQgZnVuY3Rpb25zIGZyb20gdGhlIFtgdGlkeXZlcnNlYF0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0sIGFuZCBtb3JlIHNwZWNpZmljYWxseSB0aGUgW2B0aWR5bW9kZWxzYF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3RpZHltb2RlbHMvdGlkeW1vZGVscy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gcGFja2FnZS9lY29zeXN0ZW0gcHJpbWFyaWx5IGRldmVsb3BlZCBhbmQgbWFpbnRhaW5lZCBieSBbTWF4IEt1aG5dKGh0dHBzOi8vcmVzb3VyY2VzLnJzdHVkaW8uY29tL2F1dGhvcnMvbWF4LWt1aG4pe3RhcmdldD0iX2JsYW5rIn0gYW5kIFtEYXZpcyBWYXVnaGFuXShodHRwczovL3Jlc291cmNlcy5yc3R1ZGlvLmNvbS9hdXRob3JzL2RhdmlzLXZhdWdoYW4pe3RhcmdldD0iX2JsYW5rIn0uIApUaGlzIHBhY2thZ2UgbG9hZHMgbW9yZSBtb2RlbGluZyByZWxhdGVkIHBhY2thZ2VzIGxpa2UgYHJzYW1wbGVgLCBgcmVjaXBlc2AsIGBwYXJzbmlwYCwgYHlhcmRzdGlja2AsIGB3b3JrZmxvd3NgLCBhbmQgYHR1bmVgIHBhY2thZ2VzLiAKClRoZSB0aWR5dmVyc2UgaXMgYSBsaWJyYXJ5IG9mIHBhY2thZ2VzIGNyZWF0ZWQgYnkgUlN0dWRpby4gCldoaWxlIHNvbWUgc3R1ZGVudHMgbWF5IGJlIGZhbWlsaWFyIHdpdGggcHJldmlvdXMgUiBwcm9ncmFtbWluZyBwYWNrYWdlcywgdGhlc2UgcGFja2FnZXMgbWFrZSBkYXRhIHNjaWVuY2UgaW4gUiBlc3BlY2lhbGx5IGxlZ2libGUgYW5kIGludHVpdGl2ZS4KCgpgYGB7ciwgb3V0LndpZHRoID0gIjIwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly90aWR5dmVyc2UudGlkeXZlcnNlLm9yZy9sb2dvLnBuZyIpCmBgYAoKVGhlIHNraWxscywgbWV0aG9kcywgYW5kIGNvbmNlcHRzIHRoYXQgc3R1ZGVudHMgd2lsbCBiZSBmYW1pbGlhciB3aXRoIGJ5IHRoZSBlbmQgb2YgdGhpcyBjYXNlIHN0dWR5IGFyZToKCgo8dT4qKkRhdGEgU2NpZW5jZSBMZWFybmluZyBPYmplY3RpdmVzOioqPC91PiAKICAKMS4gRmFtaWxpYXJpdHkgd2l0aCB0aGUgdGlkeW1vZGVscyBlY29zeXN0ZW0KMi4gQWJpbGl0eSB0byBldmFsdWF0ZSBjb3JyZWxhdGlvbiBhbW9uZyBwcmVkaWN0b3IgdmFyaWFibGVzIChgY29ycnBsb3RgIGFuZCBgR0dhbGx5YCkKMy4gQWJpbGl0eSB0byBpbXBsZW1lbnQgdGlkeW1vZGVscyBwYWNrYWdlcyBzdWNoIGFzIGByc2FtcGxlYCB0byBzcGxpdCB0aGUgZGF0YSBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nIHNldHMgYXMgd2VsbCBhcyBjcm9zcyB2YWxpZGF0aW9uIHNldHMuCjQuIEFiaWxpdHkgdG8gdXNlIHRoZSBgcmVjaXBlc2AsIGBwYXJzbmlwYCwgYW5kIGB3b3JrZmxvd3NgIHRvIHRyYWluIGFuZCB0ZXN0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgYW5kIHJhbmRvbSBmb3Jlc3QgbW9kZWwKNS4gRGVtb25zdHJhdGUgaG93IHRvIHZpc3VhbGl6ZSBnZW8tc3BhdGlhbCBkYXRhIHVzaW5nIGBnZ3Bsb3QyYAoKPHU+KipTdGF0aXN0aWNhbCBMZWFybmluZyBPYmplY3RpdmVzOioqPC91PiAgCiAgCjEuIEJhc2ljIHVuZGVyc3RhbmRpbmcgdGhlIHV0aWxpdHkgb2YgbWFjaGluZSBsZWFybmluZyBmb3IgcHJlZGljdGlvbiBhbmQgY2xhc3NpZmljYXRpb24KMi4gVW5kZXJzdGFuZGluZyBvZiB0aGUgbmVlZCBmb3IgdHJhaW5pbmcgYW5kIHRlc3Qgc2V0cwozLiBVbmRlcnN0YW5kaW5nIG9mIHRoZSB1dGlsaXR5IG9mIGNyb3NzIHZhbGlkYXRpb24KNC4gVW5kZXJzdGFuZGluZyBvZiByYW5kb20gZm9yZXN0CjUuIEhvdyB0byBpbnRlcnByZXQgcm9vdCBtZWFuIHNxdWFyZWQgZXJyb3IgKHJtc2UpIHRvIGFzc2VzcyBwZXJmb3JtYW5jZSBmb3IgcHJlZGljdGlvbgoKCgpgYGB7ciwgb3V0LndpZHRoID0gIjEwMHB4IiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3Bicy50d2ltZy5jb20vbWVkaWEvRGtCRnBTc1c0QUl5eUlOLnBuZyIpCmBgYAoKCldlIHdpbGwgYmVnaW4gYnkgbG9hZGluZyB0aGUgcGFja2FnZXMgdGhhdCB3ZSB3aWxsIG5lZWQ6CgpgYGB7cn0KbGlicmFyeShoZXJlKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHNraW1yKQpsaWJyYXJ5KHN1bW1hcnl0b29scykKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShjb3JycGxvdCkKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkoR0dhbGx5KQpsaWJyYXJ5KHRpZHltb2RlbHMpCmxpYnJhcnkod29ya2Zsb3dzKQpsaWJyYXJ5KHZpcCkKbGlicmFyeSh0dW5lKQpsaWJyYXJ5KHJhbmRvbUZvcmVzdCkKbGlicmFyeShkb1BhcmFsbGVsKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeSh0aWR5cikKbGlicmFyeShsd2dlb20pCmxpYnJhcnkoc2YpCmxpYnJhcnkobWFwcykKbGlicmFyeShybmF0dXJhbGVhcnRoKQpsaWJyYXJ5KHJnZW9zKQpsaWJyYXJ5KHBhdGNod29yaykKYGBgCgoKIDx1PioqUGFja2FnZXMgdXNlZCBpbiB0aGlzIGNhc2Ugc3R1ZHk6KiogPC91PgoKUGFja2FnZSAgIHwgVXNlIGluIHRoaXMgY2FzZSBzdHVkeSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQpbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL2plbm55YmMvaGVyZV9oZXJlKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgIHwgdG8gZWFzaWx5IGxvYWQgYW5kIHNhdmUgZGF0YQpbcmVhZHJdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGltcG9ydCBDU1YgZmlsZXMKW2RwbHlyXShodHRwczovL2RwbHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byB2aWV3L2FycmFuZ2UvZmlsdGVyL3NlbGVjdC9jb21wYXJlIHNwZWNpZmljIHN1YnNldHMgb2YgZGF0YSAKW3NraW1yXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2tpbXIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIGRhdGEKW3N1bW1hcnl0b29sc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhIGluIGEgZGlmZmVyZW50IHN0eWxlClttYWdyaXR0cl0oaHR0cHM6Ly9tYWdyaXR0ci50aWR5dmVyc2Uub3JnL2FydGljbGVzL21hZ3JpdHRyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHVzZSB0aGUgYCU8PiVgIHBpcHBpbmcgb3BlcmF0b3IgCltjb3JycGxvdF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2NvcnJwbG90L3ZpZ25ldHRlcy9jb3JycGxvdC1pbnRyby5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gbWFrZSBsYXJnZSBjb3JyZWxhdGlvbiBwbG90cwpbR0dhbGx5XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvR0dhbGx5L0dHYWxseS5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBtYWtlIHNtYWxsZXIgY29ycmVsYXRpb24gcGxvdHMgIApbdGlkeW1vZGVsc10oaHR0cHM6Ly93d3cudGlkeW1vZGVscy5vcmcpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBsb2FkIGluIGEgc2V0IG9mIHBhY2thZ2VzIChicm9vbSwgZGlhbHMsIGluZmVyLCBwYXJzbmlwLCBwdXJyciwgcmVjaXBlcywgcnNhbXBsZSwgdGliYmxlLCB5YXJkc3RpY2spCltyc2FtcGxlXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JzYW1wbGUvYXJ0aWNsZXMvQmFzaWNzLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHNwbGl0IHRoZSBkYXRhIGludG8gdGVzdGluZyBhbmQgdHJhaW5pbmcgc2V0czsgdG8gc3BsaXQgdGhlIHRyYWluaW5nIHNldCBmb3IgY3Jvc3MtdmFsaWRhdGlvbiAgCltyZWNpcGVzXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JlY2lwZXMvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBwcmUtcHJvY2VzcyBkYXRhIGZvciBtb2RlbGluZyBpbiBhIHRpZHkgYW5kIHJlcHJvZHVjaWJsZSB3YXkgYW5kIHRvIGV4dHJhY3QgcHJlLXByb2Nlc3NlZCBkYXRhIChtYWpvciBmdW5jdGlvbnMgYXJlIGByZWNpcGUoKWAgLCBgcHJlcCgpYCBhbmQgdmFyaW91cyB0cmFuc2Zvcm1hdGlvbiBgc3RlcF8qKClgIGZ1bmN0aW9ucywgYXMgd2VsbCBhcyBganVpY2UoKWAgLSBleHRyYWN0cyBmaW5hbCBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgYW5kIGBiYWtlKClgIC0gYXBwbGllcyByZWNpcGUgc3RlcHMgdG8gdGVzdGluZyBkYXRhKS4gU2VlIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmVjaXBlcy9yZWNpcGVzLnBkZil7dGFyZ2V0PSJfYmxhbmsifSAgZm9yIG1vcmUgaW5mby4KW3BhcnNuaXBdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcGFyc25pcC8pe3RhcmdldD0iX2JsYW5rIn0gICB8IGFuIGludGVyZmFjZSB0byBjcmVhdGUgbW9kZWxzIChtYWpvciBmdW5jdGlvbnMgYXJlIGBmaXQoKWAsIGBzZXRfZW5naW5lKClgKQpbeWFyZHN0aWNrXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3lhcmRzdGljay8pe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIGV2YWx1YXRlIHRoZSBwZXJmb3JtYW5jZSBvZiBtb2RlbHMKW2Jyb29tXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnL2Jsb2cvMjAxOC8wNy9icm9vbS0wLTUtMC8pe3RhcmdldD0iX2JsYW5rIn0gfCB0byBnZXQgdGlkeSBvdXRwdXQgZm9yIG91ciBtb2RlbCBmaXQgYW5kIHBlcmZvcm1hbmNlCltnZ3Bsb3QyXShodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgfCB0byBtYWtlIHZpc3VhbGl6YXRpb25zIHdpdGggbXVsdGlwbGUgbGF5ZXJzCltkaWFsc10oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy9ibG9nLzIwMTkvMTAvZGlhbHMtMC0wLTMvKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gc3BlY2lmeSBoeXBlci1wYXJhbWV0ZXIgdHVuaW5nClt0dW5lXShodHRwczovL3R1bmUudGlkeW1vZGVscy5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gcGVyZm9ybSBjcm9zcyB2YWxpZGF0aW9uLCB0dW5lIGh5cGVyLXBhcmFtZXRlcnMsIGFuZCBnZXQgcGVyZm9ybWFuY2UgbWV0cmljcwpbd29ya2Zsb3dzXShodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvd29ya2Zsb3dzL3ZlcnNpb25zLzAuMS4xKXt0YXJnZXQ9Il9ibGFuayJ9fCB0byBjcmVhdGUgbW9kZWxpbmcgd29ya2Zsb3cgdG8gc3RyZWFtbGluZSB0aGUgbW9kZWxpbmcgcHJvY2VzcwpbdmlwXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvdmlwL3ZpcC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBjcmVhdGUgdmFyaWFibGUgaW1wb3J0YW5jZSBwbG90cwpbcmFuZG9tRm9yZXN0XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmFuZG9tRm9yZXN0L3JhbmRvbUZvcmVzdC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBwZXJmb3JtIHRoZSByYW5kb20gZm9yZXN0IGFuYWx5c2lzCltkb1BhcmFsbGVsXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZG9QYXJhbGxlbC9kb1BhcmFsbGVsLnBkZikgfCB0byBmaXQgY3Jvc3MgdmFsaWRhdGlvbiBzYW1wbGVzIGluIHBhcmFsbGVsIApbc3RyaW5ncl0oaHR0cHM6Ly9zdHJpbmdyLnRpZHl2ZXJzZS5vcmcvYXJ0aWNsZXMvc3RyaW5nci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIHwgdG8gbWFuaXB1bGF0ZSB0aGUgdGV4dCB0aGUgbWFwIGRhdGEKW3RpZHlyXShodHRwczovL3RpZHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzZXBhcmF0ZSBkYXRhIHdpdGhpbiBhIGNvbHVtbiBpbnRvIG11bHRpcGxlIGNvbHVtbnMKW3JuYXR1cmFsZWFydGhdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9ybmF0dXJhbGVhcnRoL1JFQURNRS5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gZ2V0IHRoZSBnZW9tZXRyeSBkYXRhIGZvciB0aGUgZWFydGggdG8gcGxvdCB0aGUgVVMKW21hcHNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9tYXBzL21hcHMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gZ2V0IG1hcCBkYXRhYmFzZSBkYXRhIGFib3V0IGNvdW50aWVzIHRvIGRyYXcgdGhlbSBvbiBvdXIgVVMgbWFwCltzZl0oaHR0cHM6Ly9yLXNwYXRpYWwuZ2l0aHViLmlvL3NmLyl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGNvbnZlcnQgdGhlIG1hcCBkYXRhIGludG8gYSBkYXRhIGZyYW1lCltsd2dlb21dKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9sd2dlb20vbHdnZW9tLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHVzZSB0aGUgYHNmYCBmdW5jdGlvbiB0byBjb252ZXJ0IG1hcCBnZW9ncmFwaGljYWwgZGF0YQpbcmdlb3NdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yZ2Vvcy9yZ2Vvcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byB1c2UgZ2VvbWV0cnkgZGF0YQpbcGF0Y2h3b3JrXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcGF0Y2h3b3JrL3BhdGNod29yay5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBhbGxvdyBwbG90cyB0byBiZSBjb21iaW5lZApfX18KCgpUaGUgZmlyc3QgdGltZSB3ZSB1c2UgYSBmdW5jdGlvbiwgd2Ugd2lsbCB1c2UgdGhlIGA6OmAgdG8gaW5kaWNhdGUgd2hpY2ggcGFja2FnZSB3ZSBhcmUgdXNpbmcuIApVbmxlc3Mgd2UgaGF2ZSBvdmVybGFwcGluZyBmdW5jdGlvbiBuYW1lcywgdGhpcyBpcyBub3QgbmVjZXNzYXJ5LCBidXQgd2Ugd2lsbCBpbmNsdWRlIGl0IGhlcmUgdG8gYmUgaW5mb3JtYXRpdmUgYWJvdXQgd2hlcmUgdGhlIGZ1bmN0aW9ucyB3ZSB3aWxsIHVzZSBjb21lIGZyb20uCgoKIyAqKkNvbnRleHQqKgoqKioKClRoZSBbU3RhdGUgb2YgR2xvYmFsIEFpcl0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9IGlzIGEgcmVwb3J0IHJlbGVhc2VkIGV2ZXJ5IHllYXIgdG8gY29tbXVuaWNhdGUgdGhlIGltcGFjdCBvZiBhaXIgcG9sbHV0aW9uIG9uIHB1YmxpYyBoZWFsdGguIAoKVGhlIFtTdGF0ZSBvZiBHbG9iYWwgQWlyIDIwMTkgcmVwb3J0XShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3NvZ2FfMjAxOV9yZXBvcnQucGRmKXt0YXJnZXQ9Il9ibGFuayJ9CndoaWNoIHVzZXMgZGF0YSBmcm9tIDIwMTcgc3RhdGVkIHRoYXQ6Cgo+IEFpciBwb2xsdXRpb24gaXMgdGhlICoqZmlmdGgqKiBsZWFkaW5nIHJpc2sgZmFjdG9yIGZvciBtb3J0YWxpdHkgd29ybGR3aWRlLiBJdCBpcyByZXNwb25zaWJsZSBmb3IgbW9yZQpkZWF0aHMgdGhhbiBtYW55IGJldHRlci1rbm93biByaXNrIGZhY3RvcnMgc3VjaCBhcyBtYWxudXRyaXRpb24sIGFsY29ob2wgdXNlLCBhbmQgcGh5c2ljYWwgaW5hY3Rpdml0eS4KRWFjaCB5ZWFyLCAqKm1vcmUqKiBwZW9wbGUgZGllIGZyb20gYWlyIHBvbGx1dGlvbuKAk3JlbGF0ZWQgZGlzZWFzZSB0aGFuIGZyb20gcm9hZCAqKnRyYWZmaWMgaW5qdXJpZXMqKiBvciAqKm1hbGFyaWEqKi4KCjxwIGFsaWduPSJjZW50ZXIiPgo8aW1nIHdpZHRoPSI2MDAiIHNyYz0iaHR0cHM6Ly93d3cuaGVhbHRoZWZmZWN0cy5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9Tb0dBLUZpZ3VyZXMtMDEuanBnIj4KPC9wPgoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3NvZ2FfMjAxOV9yZXBvcnQucGRmKXt0YXJnZXQ9Il9ibGFuayJ9CgpUaGUgcmVwb3J0IGFsc28gc3RhdGVkIHRoYXQ6Cgo+IEluIDIwMTcsIGFpciBwb2xsdXRpb24gaXMgZXN0aW1hdGVkIHRvIGhhdmUgY29udHJpYnV0ZWQgdG8gY2xvc2UgdG8gNSBtaWxsaW9uCmRlYXRocyBnbG9iYWxseSDigJQgbmVhcmx5ICoqMSBpbiBldmVyeSAxMCBkZWF0aHMqKi4KCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCIyMDE3ZGVhdGhzLnBuZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhXzIwMTlfZmFjdF9zaGVldC5wZGYpe3RhcmdldD0iX2JsYW5rIn0KClRoZSBbU3RhdGUgb2YgR2xvYmFsIEFpciAyMDE4IHJlcG9ydF0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhLTIwMTgtcmVwb3J0LnBkZil7dGFyZ2V0PSJfYmxhbmsifSB1c2luZyBkYXRhIGZyb20gMjAxNiB3aGljaCBzZXBhcmF0ZWQgZGlmZmVyZW50IHR5cGVzIG9mIGFpciBwb2xsdXRpb24sIGZvdW5kIHRoYXQgKipwYXJ0aWN1bGF0ZSBwb2xsdXRpb24gd2FzIHBhcnRpY3VsYXJseSBhc3NvY2lhdGVkIHdpdGggbW9ydGFsaXR5KiouCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiMjAxN21vcnRhbGl0eS5wbmciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LnN0YXRlb2ZnbG9iYWxhaXIub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvc29nYS0yMDE4LXJlcG9ydC5wZGYpe3RhcmdldD0iX2JsYW5rIn0KClRoZSAyMDE5IHJlcG9ydCBzaG93cyB0aGF0IHRoZSBoaWdoZXN0IGxldmVscyBvZiBmaW5lIHBhcnRpY3VsYXRlIHBvbGx1dGlvbiBvY2N1cnMgaW4gQWZyaWNhIGFuZCBBc2lhIGFuZCB0aGF0OgoKPiBNb3JlIHRoYW4gKio5MCUqKiBvZiBwZW9wbGUgd29ybGR3aWRlIGxpdmUgaW4gYXJlYXMgKipleGNlZWRpbmcqKiB0aGUgV29ybGQgSGVhbHRoIE9yZ2FuaXphdGlvbiAoV0hPKSAqKkd1aWRlbGluZSoqIGZvciBoZWFsdGh5IGFpci4gTW9yZSB0aGFuIGhhbGYgbGl2ZSBpbiBhcmVhcyB0aGF0IGRvIG5vdCBldmVuIG1lZXQgV0hPJ3MgbGVhc3Qtc3RyaW5nZW50IGFpciBxdWFsaXR5IHRhcmdldC4KCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJQTXdvcmxkLnBuZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhXzIwMTlfZmFjdF9zaGVldC5wZGYpe3RhcmdldD0iX2JsYW5rIn0KCkxvb2tpbmcgYXQgdGhlIFVTIHNwZWNpZmljYWxseSwgYWlyIHBvbGx1dGlvbiBsZXZlbHMgYXJlIGdlbmVyYWxseSBpbXByb3ZpbmcsIHdpdGggZGVjbGluaW5nIG5hdGlvbmFsIGFpciBwb2xsdXRhbnQgY29uY2VudHJhdGlvbiBhdmVyYWdlcyBhcyBzaG93biBmcm9tIHRoZSAyMDE5IFsqT3VyIE5hdGlvbidzIEFpcipdKGh0dHBzOi8vZ2lzcHViLmVwYS5nb3YvYWlyL3RyZW5kc3JlcG9ydC8yMDE5LyNob21lKXt0YXJnZXQ9Il9ibGFuayJ9IHJlcG9ydCBmcm9tIHRoZSBVUyBFbnZpcm9ubWVudGFsIFByb3RlY3Rpb24gQWdlbmN5IChFUEEpOiAKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJVUy5wbmciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vZ2lzcHViLmVwYS5nb3YvYWlyL3RyZW5kc3JlcG9ydC8yMDE5L2RvY3VtZW50YXRpb24vQWlyVHJlbmRzX0ZseWVyLnBkZil7dGFyZ2V0PSJfYmxhbmsifQoKSG93ZXZlciwgYWlyIHBvbGx1dGlvbiAqKmNvbnRpbnVlcyB0byBjb250cmlidXRlIHRvIGhlYWx0aCByaXNrIGZvciBBbWVyaWNhbnMqKiwgaW4gcGFydGljdWxhciBpbiAqKnJlZ2lvbnMgd2l0aCBoaWdoZXIgdGhhbiBuYXRpb25hbCBhdmVyYWdlIHJhdGVzKiogb2YgcG9sbHV0aW9uIHRoYXQgYWN0dWFsbHkgYXQgdGltZSBleGNlZWQgdGhlIFdITydzIHJlY29tbWVuZGVkIGxldmVsLiAKVGh1cywgaXQgaXMgaW1wb3J0YW50IHRvIG9idGFpbiBoaWdoIHNwYXRpYWwgZ3JhbnVsYXJpdHkgaW4gZXN0aW1hdGVzIG9mIGFpciBwb2xsdXRpb24gaW4gb3JkZXIgdG8gaWRlbnRpZnkgbG9jYXRpb25zIHdoZXJlIHBvcHVsYXRpb25zIGFyZSBleHBlcmllbmNpbmcgaGFybWZ1bCBsZXZlbHMgb2YgZXhwb3N1cmUuCgpZb3UgY2FuIHNlZSB0aGF0IGN1cnJlbnQgYWlyIHF1YWxpdHkgY29uZGl0aW9ucyBhdCB0aGlzIFt3ZWJzaXRlXShodHRwczovL2FxaWNuLm9yZy9jaXR5L3VzYS8pe3RhcmdldD0iX2JsYW5rIn0gYW5kIHlvdSB3aWxsIG5vdGljZSB2YXJpYXRpb24gYWNyb3NzIGRpZmZlcmVudCBjaXRpZXMuCgpGb3IgZXhhbXBsZSwgaGVyZSBhcmUgdGhlIGNvbmRpdGlvbnMgaW4gVG9wZWthIEthbnNhcyBhdCB0aGUgdGltZSB0aGlzIGNhc2Ugc3R1ZHkgd2FzIGNyZWF0ZWQ6CgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiS2Fuc2FzLnBuZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9hcWljbi5vcmcvY2l0eS91c2EvKXt0YXJnZXQ9Il9ibGFuayJ9CgpJdCByZXBvcnRzIHBhcnRpY3VsYXRlIHZhbHVlcyB1c2luZyB3aGF0IGlzIGNhbGxlZCB0aGUgW0FpciBRdWFsaXR5IEluZGV4XShodHRwczovL3d3dy5haXJub3cuZ292L2luZGV4LmNmbT9hY3Rpb249YXFpYmFzaWNzLmFxaSl7dGFyZ2V0PSJfYmxhbmsifSAoQVFJKS4KVGhpcyBbY2FsY3VsYXRvcl0oaHR0cHM6Ly9haXJub3cuZ292L2luZGV4LmNmbT9hY3Rpb249YWlybm93LmNhbGN1bGF0b3Ipe3RhcmdldD0iX2JsYW5rIn0gaW5kaWNhdGVzIHRoYXQgMTE0IEFRSSBpcyBlcXVpdmFsZW50IHRvIDQwLjcgdWcvbV4zXiBhbmQgaXMgY29uc2lkZXJlZCB1bmhlYWx0aHkgZm9yIHNlbnNpdGl2ZSBpbmRpdmlkdWFscy4KVGh1cywgc29tZSBhcmVhcyBleGNlZWQgdGhlIFdITyBhbm51YWwgZXhwb3N1cmUgZ3VpZGVsaW5lICgxMCB1Zy9tXjNeKSBhbmQgdGhpcyBtYXkgYWR2ZXJzZWx5IGFmZmVjdCB0aGUgaGVhbHRoIG9mIHBlb3BsZSBsaXZpbmcgaW4gdGhlc2UgbG9jYXRpb25zLgoKQWR2ZXJzZSBoZWFsdGggZWZmZWN0cyBoYXZlIGJlZW4gYXNzb2NpYXRlZCB3aXRoIHBvcHVsYXRpb25zIGV4cGVyaWVuY2luZyBoaWdoZXIgcG9sbHV0aW9uIGV4cG9zdXJlIGRlc3BpdGUgdGhlIGxldmVscyBiZWluZyBiZWxvdyBzdWdnZXN0ZWQgZ3VpZGVsaW5lcy4gCkFsc28sIGl0IGFwcGVhcnMgdGhhdCB0aGUgY29tcG9zaXRpb24gb2YgdGhlIHBhcnRpY3VsYXRlIG1hdHRlciBhbmQgdGhlIGluZmx1ZW5jZSBvZiBvdGhlciBkZW1vZ3JhcGhpYyBmYWN0b3JzIG1heSBtYWtlIHNwZWNpZmljIHBvcHVsYXRpb25zIG1vcmUgYXQgcmlzayBmb3IgYWR2ZXJzZSBoZWFsdGggZWZmZWN0cyBkdWUgdG8gYWlyIHBvbGx1dGlvbi4gCkZvciBleGFtcGxlLCBzZWUgdGhpcyBbYXJ0aWNsZV0oaHR0cHM6Ly93d3cubmVqbS5vcmcvZG9pL2Z1bGwvMTAuMTA1Ni9ORUpNb2ExNzAyNzQ3KXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGRldGFpbHMuCgpUaGUgbW9uaXRvciBkYXRhIHRoYXQgd2Ugd2lsbCB1c2UgaW4gdGhpcyBjYXNlIHN0dWR5IGNvbWUgZnJvbSBhIHN5c3RlbSBvZiBtb25pdG9ycyBpbiB3aGljaCByb3VnaGx5IDkwJSBhcmUgbG9jYXRlZCB3aXRoaW4gY2l0aWVzLiAKSGVuY2UsIHRoZXJlIGlzIGFuICoqZXF1aXR5IGlzc3VlKiogaW4gdGVybXMgb2YgY2FwdHVyaW5nIHRoZSBhaXIgcG9sbHV0aW9uIGxldmVscyBvZiBtb3JlIHJ1cmFsIGFyZWFzLiAKVG8gZ2V0IGEgYmV0dGVyIHNlbnNlIG9mIHRoZSBwb2xsdXRpb24gZXhwb3N1cmVzIGZvciB0aGUgaW5kaXZpZHVhbHMgbGl2aW5nIGluIHRoZXNlIGFyZWFzLCBtZXRob2RzIGxpa2UgbWFjaGluZSBsZWFybmluZyBjYW4gYmUgdXNlZnVsIHRvIGVzdGltYXRlIGFpciBwb2xsdXRpb24gbGV2ZWxzIGluICoqYXJlYXMgd2l0aCBsaXR0bGUgdG8gbm8gbW9uaXRvcmluZyoqLiAKU3BlY2lmaWNhbGx5LCB0aGVzZSBtZXRob2RzIGNhbiBiZSB1c2VkIHRvIGVzdGltYXRlIGFpciBwb2xsdXRpb24gaW4gdGhlc2UgbG93IG1vbml0b3JpbmcgYXJlYXMgc28gdGhhdCB3ZSBjYW4gbWFrZSBhIG1hcCBsaWtlIHRoaXMgd2hlcmUgd2UgaGF2ZSBhbm51YWwgZXN0aW1hdGVzIGZvciBhbGwgb2YgdGhlIGNvbnRpZ3VvdXMgVVM6Cgo8cCBhbGlnbj0iY2VudGVyIj4KICA8aW1nIHdpZHRoPSI2MDAiIHNyYz0iaHR0cHM6Ly9hcmMtYW5nbGVyZmlzaC13YXNocG9zdC1wcm9kLXdhc2hwb3N0LnMzLmFtYXpvbmF3cy5jb20vcHVibGljL1NBV09FR0JYTVZHUTdBUzVQWjZVVU9YNkZZLnBuZyI+CjwvcD4KCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS91cmw/c2E9aSZ1cmw9aHR0cHMlM0ElMkYlMkZ3d3cud2FzaGluZ3RvbnBvc3QuY29tJTJGYnVzaW5lc3MlMkYyMDE5JTJGMTAlMkYyMyUyRmFpci1wb2xsdXRpb24taXMtZ2V0dGluZy13b3JzZS1kYXRhLXNob3ctbW9yZS1wZW9wbGUtYXJlLWR5aW5nJTJGJnBzaWc9QU92VmF3M3YtWkRUQlBuTFAyTVl0S2YzVW5kaiZ1c3Q9MTU4NTc4NDQ3OTA2ODAwMCZzb3VyY2U9aW1hZ2VzJmNkPXZmZSZ2ZWQ9MENBSVFqUnhxRndvVENQQ3luOWZ4eGVnQ0ZRQUFBQUFkQUFBQUFCQWQpe3RhcmdldD0iX2JsYW5rIn0KClRoaXMgaXMgd2hhdCB3ZSBhaW0gdG8gYWNoaWV2ZSBpbiB0aGlzIGNhc2Ugc3R1ZHkuCgojICoqTGltaXRhdGlvbnMqKgoqKioKClRoZXJlIGFyZSBzb21lIGltcG9ydGFudCBjb25zaWRlcmF0aW9ucyByZWdhcmRpbmcgdGhlIGRhdGEgYW5hbHlzaXMgaW4gdGhpcyBjYXNlIHN0dWR5IHRvIGtlZXAgaW4gbWluZDogCgoxLiBUaGUgZGF0YSBkbyBub3QgaW5jbHVkZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgY29tcG9zaXRpb24gb2YgcGFydGljdWxhdGUgbWF0dGVyLiBEaWZmZXJlbnQgdHlwZXMgb2YgcGFydGljdWxhdGVzIG1heSBiZSBtb3JlIGJlbmlnbiBvciBkZWxldGVyaW91cyBmb3IgaGVhbHRoIG91dGNvbWVzLgoKMi4gT3V0ZG9vciBwb2xsdXRpb24gbGV2ZWxzIGFyZSBub3QgbmVjZXNzYXJpbHkgYW4gaW5kaWNhdGlvbiBvZiBpbmRpdmlkdWFsIGV4cG9zdXJlcy4gUGVvcGxlIHNwZW5kIGRpZmZlcmluZyBhbW91bnRzIG9mIHRpbWUgaW5kb29ycyBhbmQgb3V0ZG9vcnMgYW5kIGFyZSBleHBvc2VkIHRvIGRpZmZlcmVudCBwb2xsdXRpb24gbGV2ZWxzIGluZG9vcnMuIFJlc2VhcmNoZXJzIGFyZSBub3cgZGV2ZWxvcGluZyBwZXJzb25hbCBtb25pdG9yaW5nIHN5c3RlbXMgdG8gdHJhY2sgYWlyIHBvbGx1dGlvbiBsZXZlbHMgb24gdGhlIHBlcnNvbmFsIGxldmVsLgoKMy4gT3VyIGFuYWx5c2lzIHdpbGwgdXNlIGFubnVhbCBtZWFuIGVzdGltYXRlcyBvZiBwb2xsdXRpb24gbGV2ZWxzLCBidXQgdGhlc2UgY2FuIHZhcnkgZ3JlYXRseSBieSBzZWFzb24sIGRheSBhbmQgZXZlbiBob3VyLiBUaGVyZSBhcmUgZGF0YSBzb3VyY2VzIHRoYXQgaGF2ZSBmaW5lciBsZXZlbHMgb2YgdGVtcG9yYWwgZGF0YSwgaG93ZXZlciB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBsb25nIHRlcm0gZXhwb3N1cmVzLCBhcyB0aGVzZSBhcHBlYXIgdG8gYmUgdGhlIG1vc3QgaW5mbHVlbnRpYWwgZm9yIGhlYWx0aCBvdXRjb21lcywgc28gd2UgY2hvc2UgdG8gdXNlIGFubnVhbCBsZXZlbCBkYXRhLiAKCgojICoqV2hhdCBhcmUgdGhlIGRhdGE/KiogeyN3aGF0YXJldGhlZGF0YX0KKioqCgpXaGVuIHVzaW5nIG1hY2hpbmUgbGVhcm5pbmcgZm9yIHByZWRpY3Rpb24sIHRoZXJlIGFyZSB0d28gbWFpbiB0eXBlcyBvZiBkYXRhIG9mIGludGVyZXN0OgoKMS4gQW4gKipjb250aW51b3VzKiogb3V0Y29tZSB2YXJpYWJsZSB0aGF0IHdlIHdhbnQgdG8gcHJlZGljdCAKMi4gQSBzZXQgb2YgZmVhdHVyZShzKSAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykgdGhhdCB3ZSB1c2UgdG8gcHJlZGljdCB0aGUgb3V0Y29tZSB2YXJpYWJsZQoKVGhlICoqb3V0Y29tZSB2YXJpYWJsZSoqIGlzIHdoYXQgYXJlIHRyeWluZyB0byAqKnByZWRpY3QqKi4gClRvIGJ1aWxkIChvciB0cmFpbikgb3VyIG1vZGVsLCB3ZSB1c2UgYm90aCB0aGUgb3V0Y29tZSBhbmQgZmVhdHVyZXMuClRoZSBnb2FsIGlzIHRvIGlkZW50aWZ5IGluZm9ybWF0aXZlIGZlYXR1cmVzIHRoYXQgY2FuIGV4cGxhaW4gYSBsYXJnZSBhbW91bnQgb2YgdmFyaWF0aW9uIGluIG91ciBvdXRjb21lIHZhcmlhYmxlLiAKVXNpbmcgdGhpcyBtb2RlbCwgd2UgY2FuIHRoZW4gcHJlZGljdCB0aGUgb3V0Y29tZSBmcm9tIG5ldyBvYnNlcnZhdGlvbnMgd2l0aCB0aGUgc2FtZSBmZWF0dXJlcyB3aGVyZSBoYXZlIG5vdCBvYnNlcnZlZCB0aGUgb3V0Y29tZS4gCgpBcyBhIHNpbXBsZSBleGFtcGxlLCBpbWFnaW5lIHRoYXQgd2UgaGF2ZSBkYXRhIGFib3V0IHRoZSBzYWxlcyBhbmQgY2hhcmFjdGVyaXN0aWNzIG9mIGNhcnMgZnJvbSBsYXN0IHllYXIgYW5kIHdlIHdhbnQgdG8gcHJlZGljdCB3aGljaCBjYXJzIG1pZ2h0IHNlbGwgd2VsbCB0aGlzIHllYXIuIApXZSBkbyBub3QgaGF2ZSB0aGUgc2FsZXMgZGF0YSB5ZXQgZm9yIHRoaXMgeWVhciwgYnV0IHdlIGRvIGtub3cgdGhlIGNoYXJhY3RlcmlzdGljcyBvZiBvdXIgY2FycyBmb3IgdGhpcyB5ZWFyLiAKV2UgY2FuIGJ1aWxkIGEgbW9kZWwgb2YgdGhlIGNoYXJhY3RlcmlzdGljcyB0aGF0IGV4cGxhaW5lZCBzYWxlcyBsYXN0IHllYXIgdG8gZXN0aW1hdGUgd2hhdCBjYXJzIG1pZ2h0IHNlbGwgd2VsbCB0aGlzIHllYXIuIApJbiB0aGlzIGNhc2UsIG91ciBvdXRjb21lIHZhcmlhYmxlIGlzIHRoZSBzYWxlcyBvZiBjYXJzLCB3aGlsZSB0aGUgZGlmZmVyZW50IGNoYXJhY3RlcmlzdGljcyBvZiB0aGUgY2FycyBtYWtlIHVwIG91ciBmZWF0dXJlcy4KCiMjIyBTdGFydCB3aXRoIGEgcXVlc3Rpb24KClRoaXMgaXMgdGhlIG1vc3QgY29tbW9ubHkgbWlzc2VkIHN0ZXAgd2hlbiBkZXZlbG9waW5nIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0uIApNYWNoaW5lIGxlYXJuaW5nIGNhbiB2ZXJ5IGVhc2lseSBiZSB0dXJuZWQgaW50byBhbiBlbmdpbmVlcmluZyBwcm9ibGVtLiAKSnVzdCBkdW1wIHRoZSBvdXRjb21lIGFuZCB0aGUgZmVhdHVyZXMgaW50byBhIGJsYWNrIGJveCBhbGdvcml0aG0gYW5kIHZpb2xhISAKQnV0IHRoaXMga2luZCBvZiB0aGlua2luZyBjYW4gbGVhZCB0byBtYWpvciBwcm9ibGVtcy4gSW4gZ2VuZXJhbCBnb29kIG1hY2hpbmUgbGVhcm5pbmcgcXVlc3Rpb25zOgoKMS4gSGF2ZSBhIHBsYXVzaWJsZSBleHBsYW5hdGlvbiBmb3Igd2h5IHRoZSBmZWF0dXJlcyBwcmVkaWN0IHRoZSBvdXRjb21lLiAKMi4gQ29uc2lkZXIgcG90ZW50aWFsIHZhcmlhdGlvbiBpbiBib3RoIHRoZSBmZWF0dXJlcyBhbmQgdGhlIG91dGNvbWUgb3ZlciB0aW1lCjMuIEFyZSBjb25zaXN0ZW50bHkgcmUtZXZhbHVhdGVkIG9uIGNyaXRlcmlhIDEgYW5kIDIgb3ZlciB0aW1lLiAKCkluIHRoaXMgY2FzZSBzdHVkeSwgd2Ugd2FudCB0byAqKnByZWRpY3QqKiBhaXIgcG9sbHV0aW9uIGxldmVscy4gClRvIGJ1aWxkIHRoaXMgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0sIG91ciAqKm91dGNvbWUgdmFyaWFibGUqKiBpcyBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlciAoUE1+Mi41fikgY2FwdHVyZWQgZnJvbSBhaXIgcG9sbHV0aW9uIG1vbml0b3JzIGluIHRoZSBjb250aWd1b3VzIFVTIGZyb20gMjAwOC4gCk91ciAqKmZlYXR1cmVzKiogKG9yIHByZWRpY3RvciB2YXJpYWJsZXMpIGluY2x1ZGUgZGF0YSBhYm91dCBwb3B1bGF0aW9uIGRlbnNpdHksIHJvYWQgZGVuc2l0eSwgdXJiYW5pemF0aW9uIGxldmVscywgYW5kIE5BU0Egc2F0ZWxsaXRlIGRhdGEuIAoKQWxsIG9mIG91ciBkYXRhIHdhcyBwcmV2aW91c2x5IGNvbGxlY3RlZCBieSBhIFtyZXNlYXJjaGVyXShodHRwOi8vd3d3LmJpb3N0YXQuamhzcGguZWR1L35ycGVuZy8pIGF0IHRoZSBbSm9obnMgSG9wa2lucyBTY2hvb2wgb2YgUHVibGljIEhlYWx0aF0oaHR0cHM6Ly93d3cuamhzcGguZWR1Lykgd2hvIHN0dWRpZXMgYWlyIHBvbGx1dGlvbiBhbmQgY2xpbWF0ZSBjaGFuZ2UuIAoKCiMjIyBPdXIgb3V0Y29tZSB2YXJpYWJsZQoKVGhlIG1vbml0b3IgZGF0YSB0aGF0IHdlIHdpbGwgYmUgdXNpbmcgY29tZXMgZnJvbSAqKltncmF2aW1ldHJpYyBtb25pdG9yc10oaHR0cHM6Ly9wdWJsaWNsYWIub3JnL3dpa2kvZmlsdGVyLXBtKXt0YXJnZXQ9Il9ibGFuayJ9KiogKHNlZSBwaWN0dXJlIGJlbG93KSBvcGVyYXRlZCBieSB0aGUgVVMgW0Vudmlyb25tZW50YWwgUHJvdGVjdGlvbiBBZ2VuY3kgKEVQQSldKGh0dHBzOi8vd3d3LmVwYS5nb3YvKXt0YXJnZXQ9Il9ibGFuayJ9LgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSIxMDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIm1vbml0b3IucG5nIikpCmBgYAoKIyMjIyMgW2ltYWdlIGN1cnRlc3kgb2YgW0tpcnN0ZW4gS29laGxlcl0oaHR0cHM6Ly93d3cuamhzcGguZWR1L2ZhY3VsdHkvZGlyZWN0b3J5L3Byb2ZpbGUvMjkyOC9raXJzdGVuLWtvZWhsZXIpXQoKVGhlc2UgbW9uaXRvcnMgdXNlIGEgZmlsdHJhdGlvbiBzeXN0ZW0gdG8gc3BlY2lmaWNhbGx5IGNhcHR1cmUgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIuIAoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSIxNTBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsImZpbHRlci5wbmciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vcHVibGljbGFiLm9yZy93aWtpL2ZpbHRlci1wbSl7dGFyZ2V0PSJfYmxhbmsifQoKVGhlIHdlaWdodCBvZiB0aGlzIHBhcnRpY3VsYXRlIG1hdHRlciBpcyBtYW51YWxseSBtZWFzdXJlZCBkYWlseSBvciB3ZWVrbHkuIApGb3IgdGhlIEVQQSBzdGFuZGFyZCBvcGVyYXRpbmcgcHJvY2VkdXJlIGZvciBQTSBncmF2aW1ldHJpYyBhbmFseXNpcyBpbiAyMDA4LCB3ZSByZWZlciB0aGUgcmVhZGVyIHRvIFtoZXJlXShodHRwczovL3d3dzMuZXBhLmdvdi90dG5hbXRpMS9maWxlcy9hbWJpZW50L3BtMjUvc3BlYy9SVElHcmF2TWFzc1NPUEZJTkFMLnBkZil7dGFyZ2V0PSJfYmxhbmsifS4KCjxkZXRhaWxzPjxzdW1tYXJ5PkZvciBtb3JlIG9uIEdyYXZpbWV0cmljIGFuYWx5c2lzLCB5b3UgY2FuIGV4cGFuZCBoZXJlIDwvc3VtbWFyeT4KCkdyYXZpbWV0cmljIGFuYWx5c2lzIGlzIGFsc28gdXNlZCBmb3IgW2VtaXNzaW9uIHRlc3RpbmddKGh0dHBzOi8vd3d3Lm10LmNvbS91cy9lbi9ob21lL2FwcGxpY2F0aW9ucy9MYWJvcmF0b3J5X3dlaWdoaW5nL2VtaXNzaW9ucy10ZXN0aW5nLXBhcnRpY3VsYXRlLW1hdHRlci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9LiAKVGhlIHNhbWUgaWRlYSBhcHBsaWVzOiBhIGZyZXNoIGZpbHRlciBpcyBhcHBsaWVkIGFuZCB0aGUgZGVzaXJlZCBhbW91bnQgb2YgdGltZSBwYXNzZXMsIHRoZW4gdGhlIGZpbHRlciBpcyByZW1vdmVkIGFuZCB3ZWlnaGVkLiAKClRoZXJlIGFyZSBbb3RoZXIgbW9uaXRvcmluZyBzeXN0ZW1zXShodHRwczovL3d3dy5zZW5zaXJpb24uY29tL2VuL2Fib3V0LXVzL25ld3Nyb29tL3NlbnNpcmlvbi1zcGVjaWFsaXN0LWFydGljbGVzL3BhcnRpY3VsYXRlLW1hdHRlci1zZW5zaW5nLWZvci1haXItcXVhbGl0eS1tZWFzdXJlbWVudHMvKXt0YXJnZXQ9Il9ibGFuayJ9IHRoYXQgY2FuIHByb3ZpZGUgaG91cmx5IG1lYXN1cmVtZW50cywgYnV0IHdlIHdpbGwgbm90IGJlIHVzaW5nIGRhdGEgZnJvbSB0aGVzZSBtb25pdG9ycyBpbiBvdXIgYW5hbHlzaXMuIApHcmF2aW1ldHJpYyBhbmFseXNpcyBpcyBjb25zaWRlcmVkIHRvIGJlIGFtb25nIHRoZSBtb3N0IGFjY3VyYXRlIG1ldGhvZHMgZm9yIG1lYXN1cmluZyBwYXJ0aWN1bGF0ZSBtYXR0ZXIuCgo8L2RldGFpbHM+CgpJbiBvdXIgZGF0YSBzZXQsIHRoZSBgdmFsdWVgIGNvbHVtbiBpbmRpY2F0ZXMgdGhlIFBNfjIuNX4gbW9uaXRvciBhdmVyYWdlIGZvciAyMDA4IGluIG1hc3Mgb2YgZmluZSBwYXJ0aWNsZXMvdm9sdW1lIG9mIGFpciBmb3IgODc2IGdyYXZpbWV0cmljIG1vbml0b3JzLiAKVGhlIHVuaXRzIGFyZSBtaWNyb2dyYW1zIG9mIGZpbmUgcGFydGljdWxhdGUgbWF0dGVyIChQTSkgdGhhdCBpcyBsZXNzIHRoYW4gMi41IG1pY3JvbWV0ZXJzIGluIGRpYW1ldGVyIHBlciBjdWJpYyBtZXRlciBvZiBhaXIgLSBtYXNzIGNvbmNlbnRyYXRpb24gKHVnL21eM14pLgpSZWNhbGwgdGhlIFdITyBleHBvc3VyZSBndWlkZWxpbmUgaXMgPCAxMCB1Zy9tXjNeIG9uIGF2ZXJhZ2UgYW5udWFsbHkgZm9yIFBNfjIuNX4uCgojIyMgT3VyIGZlYXR1cmVzIChwcmVkaWN0b3IgdmFyaWFibGVzKSAKClRoZXJlIGFyZSA0OCBmZWF0dXJlcyB3aXRoIHZhbHVlcyBmb3IgZWFjaCBvZiB0aGUgODc2IG1vbml0b3JzIChvYnNlcnZhdGlvbnMpLiAKVGhlIGRhdGEgY29tZXMgZnJvbSB0aGUgVVMgW0Vudmlyb25tZW50YWwgUHJvdGVjdGlvbiBBZ2VuY3kgKEVQQSldKGh0dHBzOi8vd3d3LmVwYS5nb3YvKXt0YXJnZXQ9Il9ibGFuayJ9LCB0aGUgW05hdGlvbmFsIEFlcm9uYXV0aWNzIGFuZCBTcGFjZSBBZG1pbmlzdHJhdGlvbiAoTkFTQSldKGh0dHBzOi8vd3d3Lm5hc2EuZ292Lyl7dGFyZ2V0PSJfYmxhbmsifSwgdGhlIFVTIFtDZW5zdXNdKGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvYWJvdXQvd2hhdC9jZW5zdXMtYXQtYS1nbGFuY2UuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSwgYW5kIHRoZSBbTmF0aW9uYWwgQ2VudGVyIGZvciBIZWFsdGggU3RhdGlzdGljcyAoTkNIUyldKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9hYm91dC9pbmRleC5odG0pe3RhcmdldD0iX2JsYW5rIn0uCgo8ZGV0YWlscz48c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byBzZWUgYSB0YWJsZSBhYm91dCB0aGUgc2V0IG9mIGZlYXR1cmVzIDwvc3VtbWFyeT4KClZhcmlhYmxlICAgfCBEZXRhaWxzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCi0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS0KKippZCoqICB8IE1vbml0b3IgbnVtYmVyICA8YnI+IC0tIHRoZSBjb3VudHkgbnVtYmVyIGlzIGluZGljYXRlZCBiZWZvcmUgdGhlIGRlY2ltYWwgPGJyPiAtLSB0aGUgbW9uaXRvciBudW1iZXIgaXMgaW5kaWNhdGVkIGFmdGVyIHRoZSBkZWNpbWFsIDxicj4gICoqRXhhbXBsZSoqOiAxMDczLjAwMjMgIGlzIEplZmZlcnNvbiBjb3VudHkgKDEwNzMpIGFuZCAuMDAyMyBvbmUgb2YgOCBtb25pdG9ycyAKKipmaXBzKiogfCBGZWRlcmFsIGluZm9ybWF0aW9uIHByb2Nlc3Npbmcgc3RhbmRhcmQgbnVtYmVyIGZvciB0aGUgY291bnR5IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQgPGJyPiAtLSA1IGRpZ2l0IGlkIGNvZGUgZm9yIGNvdW50aWVzICh6ZXJvIGlzIG9mdGVuIHRoZSBmaXJzdCB2YWx1ZSBhbmQgc29tZXRpbWVzIGlzIG5vdCBzaG93bikgPGJyPiAtLSB0aGUgZmlyc3QgMiBudW1iZXJzIGluZGljYXRlIHRoZSBzdGF0ZSA8YnI+IC0tIHRoZSBsYXN0IHRocmVlIG51bWJlcnMgaW5kaWNhdGUgdGhlIGNvdW50eSA8YnI+ICAqKkV4YW1wbGUqKjogQWxhYmFtYSdzIHN0YXRlIGNvZGUgaXMgMDEgYmVjYXVzZSBpdCBpcyBmaXJzdCBhbHBoYWJldGljYWxseSA8YnI+IChub3RlOiBBbGFza2EgYW5kIEhhd2FpaSBhcmUgbm90IGluY2x1ZGVkIGJlY2F1c2UgdGhleSBhcmUgbm90IHBhcnQgb2YgdGhlIGNvbnRpZ3VvdXMgVVMpICAKKipMYXQqKiB8IExhdGl0dWRlIG9mIHRoZSBtb25pdG9yIGluIGRlZ3JlZXMgIAoqKkxvbioqIHwgTG9uZ2l0dWRlIG9mIHRoZSBtb25pdG9yIGluIGRlZ3JlZXMgIAoqKnN0YXRlKiogfCBTdGF0ZSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkCioqY291bnR5KiogfCBDb3VudHkgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZAoqKmNpdHkqKiB8IENpdHkgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZAoqKkNNQVEqKiAgfCBFc3RpbWF0ZWQgdmFsdWVzIG9mIGFpciBwb2xsdXRpb24gZnJvbSBhIGNvbXB1dGF0aW9uYWwgbW9kZWwgY2FsbGVkIFsqKkNvbW11bml0eSBNdWx0aXNjYWxlIEFpciBRdWFsaXR5IChDTUFRKSoqXShodHRwczovL3d3dy5lcGEuZ292L2NtYXEpe3RhcmdldD0iX2JsYW5rIn0gPGJyPiAtLSAgQSBtb25pdG9yaW5nIHN5c3RlbSB0aGF0IHNpbXVsYXRlcyB0aGUgcGh5c2ljcyBvZiB0aGUgYXRtb3NwaGVyZSB1c2luZyBjaGVtaXN0cnkgYW5kIHdlYXRoZXIgZGF0YSB0byBwcmVkaWN0IHRoZSBhaXIgcG9sbHV0aW9uIDxicj4gLS0gKioqRG9lcyBub3QgdXNlIGFueSBvZiB0aGUgUE1+Mi41fiBncmF2aW1ldHJpYyBtb25pdG9yaW5nIGRhdGEuKioqIChUaGVyZSBpcyBhIHZlcnNpb24gdGhhdCBkb2VzIHVzZSB0aGUgZ3JhdmltZXRyaWMgbW9uaXRvcmluZyBkYXRhLCBidXQgbm90IHRoaXMgb25lISkgPGJyPiAtLSBEYXRhIGZyb20gdGhlIEVQQQoqKnpjdGEqKiB8IFtaaXAgQ29kZSBUYWJ1bGF0aW9uIEFyZWFdKGh0dHBzOi8vd3d3Mi5jZW5zdXMuZ292L2dlby9wZGZzL2VkdWNhdGlvbi9icm9jaHVyZXMvWkNUQXMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQgPGJyPiAtLSBQb3N0YWwgWmlwIGNvZGVzIGFyZSBjb252ZXJ0ZWQgaW50byAiZ2VuZXJhbGl6ZWQgYXJlYWwgcmVwcmVzZW50YXRpb25zIiB0aGF0IGFyZSBub24tb3ZlcmxhcHBpbmcgIDxicj4gLS0gRGF0YSBmcm9tIHRoZSAyMDEwIENlbnN1cyAgCioqemN0YV9hcmVhKiogfCBMYW5kIGFyZWEgb2YgdGhlIHppcCBjb2RlIGFyZWEgaW4gbWV0ZXJzIHNxdWFyZWQgIDxicj4gLS0gRGF0YSBmcm9tIHRoZSAyMDEwIENlbnN1cyAgCioqemN0YV9wb3AqKiB8IFBvcHVsYXRpb24gaW4gdGhlIHppcCBjb2RlIGFyZWEgIDxicj4gLS0gRGF0YSBmcm9tIHRoZSAyMDEwIENlbnN1cyAgCioqaW1wX2E1MDAqKiB8IEltcGVydmlvdXMgc3VyZmFjZSBtZWFzdXJlIDxicj4gLS0gV2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgNTAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgPGJyPiAtLSBJbXBlcnZpb3VzIHN1cmZhY2UgYXJlIHJvYWRzLCBjb25jcmV0ZSwgcGFya2luZyBsb3RzLCBidWlsZGluZ3MgPGJyPiAtLSBUaGlzIGlzIGEgbWVhc3VyZSBvZiBkZXZlbG9wbWVudCAKKippbXBfYTEwMDAqKiB8IEltcGVydmlvdXMgc3VyZmFjZSBtZWFzdXJlIDxicj4gLS0gIFdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvcgoqKmltcF9hNTAwMCoqIHwgSW1wZXJ2aW91cyBzdXJmYWNlIG1lYXN1cmUgPGJyPiAtLSAgV2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yICAKKippbXBfYTEwMDAwKiogfCBJbXBlcnZpb3VzIHN1cmZhY2UgbWVhc3VyZSA8YnI+IC0tICBXaXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yICAgCioqaW1wX2ExNTAwMCoqIHwgSW1wZXJ2aW91cyBzdXJmYWNlIG1lYXN1cmUgPGJyPiAtLSAgV2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAgCioqY291bnR5X2FyZWEqKiB8IExhbmQgYXJlYSBvZiB0aGUgY291bnR5IG9mIHRoZSBtb25pdG9yIGluIG1ldGVycyBzcXVhcmVkICAKKipjb3VudHlfcG9wKiogfCBQb3B1bGF0aW9uIG9mIHRoZSBjb3VudHkgb2YgdGhlIG1vbml0b3IgIAoqKkxvZ19kaXN0X3RvX3ByaXNlYyoqIHwgTG9nIChOYXR1cmFsIGxvZykgZGlzdGFuY2UgdG8gYSBwcmltYXJ5IG9yIHNlY29uZGFyeSByb2FkIGZyb20gdGhlIG1vbml0b3IgPGJyPiAtLSBIaWdod2F5IG9yIG1ham9yIHJvYWQgIAoqKmxvZ19wcmlfbGVuZ3RoXzUwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgPGJyPiAtLSBIaWdod2F5cyBvbmx5ICAKKipsb2dfcHJpX2xlbmd0aF8xMDAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgPGJyPiAtLSBIaWdod2F5cyBvbmx5ICAKKipsb2dfcHJpX2xlbmd0aF8xNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgPGJyPiAtLSBIaWdod2F5cyBvbmx5ICAKKipsb2dfcHJpX2xlbmd0aF8yNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAyNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgPGJyPiAtLSBIaWdod2F5cyBvbmx5ICAKKipsb2dfcHJpc2VjX2xlbmd0aF81MDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICA8YnI+IC0tIEhpZ2h3YXkgYW5kIHNlY29uZGFyeSByb2FkcyAgCioqbG9nX3ByaXNlY19sZW5ndGhfMTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICA8YnI+IC0tIEhpZ2h3YXkgYW5kIHNlY29uZGFyeSByb2FkcyAgCioqbG9nX3ByaXNlY19sZW5ndGhfNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICA8YnI+IC0tIEhpZ2h3YXkgYW5kIHNlY29uZGFyeSByb2FkcyAgCioqbG9nX3ByaXNlY19sZW5ndGhfMTAwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICAKKipsb2dfcHJpc2VjX2xlbmd0aF8xNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDE1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgPGJyPiAtLSBIaWdod2F5IGFuZCBzZWNvbmRhcnkgcm9hZHMgIAoqKmxvZ19wcmlzZWNfbGVuZ3RoXzI1MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMjUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICA8YnI+IC0tIEhpZ2h3YXkgYW5kIHNlY29uZGFyeSByb2FkcyAgICAgIAoqKmxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xMDAwMCoqIHwgVG9ucyBvZiBlbWlzc2lvbnMgZnJvbSBtYWpvciBzb3VyY2VzIGRhdGEgYmFzZSAoYW5udWFsIGRhdGEpIHN1bSBvZiBhbGwgc291cmNlcyB3aXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwMCBtZXRlcnMgb2YgZGlzdGFuY2UgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgICAgCioqbG9nX25laV8yMDA4X3BtMjVfc3VtXzE1MDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDE1MDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgCioqbG9nX25laV8yMDA4X3BtMjVfc3VtXzI1MDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDI1MDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgCioqbG9nX25laV8yMDA4X3BtMTBfc3VtXzEwMDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgIAoqKmxvZ19uZWlfMjAwOF9wbTEwX3N1bV8xNTAwMCoqfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDE1MDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgIAoqKmxvZ19uZWlfMjAwOF9wbTEwX3N1bV8yNTAwMCoqIHwgVG9ucyBvZiBlbWlzc2lvbnMgZnJvbSBtYWpvciBzb3VyY2VzIGRhdGEgYmFzZSAoYW5udWFsIGRhdGEpIHN1bSBvZiBhbGwgc291cmNlcyB3aXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAyNTAwMCBtZXRlcnMgb2YgZGlzdGFuY2UgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgICAgICAKKipwb3BkZW5zX2NvdW50eSoqIHwgUG9wdWxhdGlvbiBkZW5zaXR5IChudW1iZXIgb2YgcGVvcGxlIHBlciBraWxvbWV0ZXIgc3F1YXJlZCBhcmVhIG9mIHRoZSBjb3VudHkpCioqcG9wZGVuc196Y3RhKiogfCBQb3B1bGF0aW9uIGRlbnNpdHkgKG51bWJlciBvZiBwZW9wbGUgcGVyIGtpbG9tZXRlciBzcXVhcmVkIGFyZWEgb2YgemN0YSkKKipub2hzKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3IgaXMgdGhhdCAqKmRvIG5vdCBoYXZlIGEgaGlnaCBzY2hvb2wgZGVncmVlKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cwoqKnNvbWVocyoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzICoqc29tZSBoaWdoIHNjaG9vbCBlZHVjYXRpb24qKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzCioqaHMqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBjb21wbGV0aW5nIGEgKipoaWdoIHNjaG9vbCBkZWdyZWUqKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzICAKKipzb21lY29sbGVnZSoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGNvbXBsZXRpbmcgKipzb21lIGNvbGxlZ2UgZWR1Y2F0aW9uKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyAKKiphc3NvY2lhdGUqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBjb21wbGV0aW5nIGFuICoqYXNzb2NpYXRlIGRlZ3JlZSoqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgCioqYmFjaGVsb3IqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBhICoqYmFjaGVsb3IncyBkZWdyZWUqKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzIAoqKmdyYWQqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBhICoqZ3JhZHVhdGUgZGVncmVlKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyAKKipwb3YqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciBpcyB0aGF0IGxpdmVkIGluIFsqKnBvdmVydHkqKl0oaHR0cHM6Ly9hc3BlLmhocy5nb3YvMjAwOC1oaHMtcG92ZXJ0eS1ndWlkZWxpbmVzKSBpbiAyMDA4IC0gb3Igd291bGQgaXQgaGF2ZSBiZWVuIDIwMDcgZ3VpZGVsaW5lcz8/aHR0cHM6Ly9hc3BlLmhocy5nb3YvMjAwNy1oaHMtcG92ZXJ0eS1ndWlkZWxpbmVzIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgIAoqKmhzX29ybGVzcyoqIHwgIFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBhICoqaGlnaCBzY2hvb2wgZGVncmVlIG9yIGxlc3MqKiAoc3VtIG9mIG5vaHMsIHNvbWVocywgYW5kIGhzKSAgCioqdXJjMjAxMyoqIHwgWzIwMTMgVXJiYW4tcnVyYWwgY2xhc3NpZmljYXRpb25dKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9kYXRhL3Nlcmllcy9zcl8wMi9zcjAyXzE2Ni5wZGYpe3RhcmdldD0iX2JsYW5rIn0gb2YgdGhlIGNvdW50eSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkIDxicj4gLS0gNiBjYXRlZ29yeSB2YXJpYWJsZSAtIDEgaXMgdG90YWxseSB1cmJhbiA2IGlzIGNvbXBsZXRlbHkgcnVyYWwgPGJyPiAgLS0gRGF0YSBmcm9tIHRoZSBbTmF0aW9uYWwgQ2VudGVyIGZvciBIZWFsdGggU3RhdGlzdGljc10oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2luZGV4Lmh0bSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgCioqdXJjMjAwNioqIHwgWzIwMDYgVXJiYW4tcnVyYWwgY2xhc3NpZmljYXRpb25dKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9kYXRhL3Nlcmllcy9zcl8wMi9zcjAyXzE1NC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gb2YgdGhlIGNvdW50eSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkIDxicj4gLS0gNiBjYXRlZ29yeSB2YXJpYWJsZSAtIDEgaXMgdG90YWxseSB1cmJhbiA2IGlzIGNvbXBsZXRlbHkgcnVyYWwgPGJyPiAtLSBEYXRhIGZyb20gdGhlIFtOYXRpb25hbCBDZW50ZXIgZm9yIEhlYWx0aCBTdGF0aXN0aWNzXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvaW5kZXguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAKKiphb2QqKiB8IEFlcm9zb2wgT3B0aWNhbCBEZXB0aCBtZWFzdXJlbWVudCBmcm9tIGEgTkFTQSBzYXRlbGxpdGUgPGJyPiAtLSBiYXNlZCBvbiB0aGUgZGlmZnJhY3Rpb24gb2YgYSBsYXNlciA8YnI+IC0tIHVzZWQgYXMgYSBwcm94eSBvZiBwYXJ0aWN1bGF0ZSBwb2xsdXRpb24gPGJyPiAtLSB1bml0LWxlc3MgLSBoaWdoZXIgdmFsdWUgaW5kaWNhdGVzIG1vcmUgcG9sbHV0aW9uIDxicj4gLS0gRGF0YSBmcm9tIE5BU0EgIAoKPC9kZXRhaWxzPgoKTWFueSBvZiB0aGVzZSBmZWF0dXJlcyBoYXZlIHRvIGRvIHdpdGggdGhlIGNpcmN1bGFyIGFyZWEgYXJvdW5kIHRoZSBtb25pdG9yIGNhbGxlZCB0aGUgImJ1ZmZlciIuIFRoZXNlIGFyZSBpbGx1c3RyYXRlZCBpbiB0aGUgZm9sbG93aW5nIGZpZ3VyZToKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aCA9ICI4MDBweCIsfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAicmVncmVzc2lvbi5wbmciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHVibWVkLzE1MjkyOTA2KXt0YXJnZXQ9Il9ibGFuayJ9CgoKCiMgKipEYXRhIEltcG9ydCoqCioqKgoKQWxsIG9mIG91ciBkYXRhIHdhcyBwcmV2aW91c2x5IGNvbGxlY3RlZCBieSBhIFtyZXNlYXJjaGVyXShodHRwOi8vd3d3LmJpb3N0YXQuamhzcGguZWR1L35ycGVuZy8pIGF0IHRoZSBbSm9obnMgSG9wa2lucyBTY2hvb2wgb2YgUHVibGljIEhlYWx0aF0oaHR0cHM6Ly93d3cuamhzcGguZWR1Lykgd2hvIHN0dWRpZXMgYWlyIHBvbGx1dGlvbiBhbmQgY2xpbWF0ZSBjaGFuZ2UuIAoKV2UgaGF2ZSBvbmUgQ1NWIGZpbGUgdGhhdCBjb250YWlucyBib3RoIG91ciBzaW5nbGUgKipvdXRjb21lIHZhcmlhYmxlKiogYW5kIGFsbCBvZiBvdXIgKipmZWF0dXJlcyoqIChvciBwcmVkaWN0b3IgdmFyaWFibGVzKS4KCk5leHQsIHdlIGltcG9ydCBvdXIgZGF0YSBpbnRvIFIgbm93IHNvIHRoYXQgd2UgY2FuIGV4cGxvcmUgdGhlIGRhdGEgZnVydGhlci4gCldlIHdpbGwgY2FsbCBvdXIgZGF0YSBvYmplY3QgYHBtYCBmb3IgcGFydGljdWxhdGUgbWF0dGVyLiAKV2UgaW1wb3J0IHRoZSBkYXRhIHVzaW5nIHRoZSBgcmVhZF9jc3YoKWAgZnVuY3Rpb24gZnJvbSB0aGUgYHJlYWRyYCBwYWNrYWdlLiAKYGBge3J9CnBtIDwtIHJlYWRyOjpyZWFkX2NzdihoZXJlKCJkb2NzIiwgInBtMjVfZGF0YS5jc3YiKSkKYGBgCgoKCiMgKipEYXRhIEV4cGxvcmF0aW9uIGFuZCBXcmFuZ2xpbmcqKgoqKioKClRoZSBmaXJzdCBzdGVwIGluIHBlcmZvcm1pbmcgYW55IGRhdGEgYW5hbHlzaXMgaXMgdG8gZXhwbG9yZSB0aGUgZGF0YS4gCgpGb3IgZXhhbXBsZSwgd2UgbWlnaHQgd2FudCB0byBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgdmFyaWFibGVzIGluY2x1ZGVkIGluIHRoZSBkYXRhLCBhcyB3ZSBtYXkgbGVhcm4gYWJvdXQgaW1wb3J0YW50IGRldGFpbHMgYWJvdXQgdGhlIGRhdGEgdGhhdCB3ZSBzaG91bGQga2VlcCBpbiBtaW5kIGFzIHdlIHRyeSB0byBwcmVkaWN0IG91ciBvdXRjb21lIHZhcmlhYmxlLgoKRmlyc3QsIGxldCdzIGp1c3QgZ2V0IGEgZ2VuZXJhbCBzZW5zZSBvZiBvdXIgZGF0YS4gCldlIGNhbiBkbyB0aGF0IHVzaW5nIHRoZSBgZ2xpbXBzZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIChpdCBpcyBhbHNvIGluIHRoZSBgdGliYmxlYCBwYWNrYWdlKS4KCldlIHdpbGwgYWxzbyB1c2UgdGhlIGAlPiVgIHBpcGUsIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGRlZmluZSB0aGUgaW5wdXQgZm9yIGxhdGVyIHNlcXVlbnRpYWwgc3RlcHMuIAoKVGhpcyB3aWxsIG1ha2UgbW9yZSBzZW5zZSB3aGVuIHdlIGhhdmUgbXVsdGlwbGUgc2VxdWVudGlhbCBzdGVwcyB1c2luZyB0aGUgc2FtZSBkYXRhIG9iamVjdC4gCgpUbyB1c2UgdGhlIHBpcGUgbm90YXRpb24gd2UgbmVlZCB0byBpbnN0YWxsIGFuZCBsb2FkIGBkcGx5cmAgYXMgd2VsbC4KCkZvciBleGFtcGxlLCBoZXJlIHdlIHN0YXJ0IHdpdGggYHBtYCBkYXRhIG9iamVjdCBhbmQgInBpcGUiIHRoZSBvYmplY3QgaW50byBhcyBpbnB1dCBpbnRvIHRoZSBgZ2xpbXBzZSgpYCBmdW5jdGlvbi4gClRoZSBvdXRwdXQgaXMgaXMgYW4gb3ZlcnZpZXcgb2Ygd2hhdCBpcyBpbiB0aGUgYHBtYCBvYmplY3Qgc3VjaCBhcyB0aGUgbnVtYmVyIG9mIHJvd3MgYW5kIGNvbHVtbnMsIGFsbCB0aGUgY29sdW1uIG5hbWVzLCB0aGUgZGF0YSB0eXBlcyBmb3IgZWFjaCBjb2x1bW4gYW5kIHRoZSBmaXJzdCB2aWV3IHZhbHVlcyBpbiBlYWNoIGNvbHVtbi4gClRoZSBvdXRwdXQgYmVsb3cgaXMgc2Nyb2xsYWJsZSBzbyB5b3UgY2FuIHNlZSBldmVyeXRoaW5nIGZyb20gdGhlIGBnbGltcHNlKClgIGZ1bmN0aW9uLiAKCiMjIyMgey5zY3JvbGxhYmxlIH0KCmBgYHtyfQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhCnBtICU+JQogIGRwbHlyOjpnbGltcHNlKCkKYGBgCgojIyMjCgpXZSBjYW4gc2VlIHRoYXQgdGhlcmUgYXJlIDg3NiBtb25pdG9ycyAocm93cykgYW5kIHRoYXQgd2UgaGF2ZSA1MCB0b3RhbCB2YXJpYWJsZXMgKGNvbHVtbnMpIC0gb25lIG9mIHdoaWNoIGlzIHRoZSBvdXRjb21lIHZhcmlhYmxlLiBJbiB0aGlzIGNhc2UsIHRoZSBvdXRjb21lIHZhcmlhYmxlIGlzIGNhbGxlZCBgdmFsdWVgLiAKCk5vdGljZSB0aGF0IHNvbWUgb2YgdGhlIHZhcmlhYmxlcyB0aGF0IHdlIHdvdWxkIHRoaW5rIG9mIGFzIGZhY3RvcnMgKG9yIGNhdGVnb3JpY2FsIGRhdGEpIGFyZSBjdXJyZW50bHkgb2YgY2xhc3MgY2hhcmFjdGVyIGFzIGluZGljYXRlZCBieSB0aGUgYDxjaHI+YCBqdXN0IHRvIHRoZSByaWdodCBvZiB0aGUgY29sdW1uIG5hbWVzL3ZhcmlhYmxlIG5hbWVzIGluIHRoZSBgZ2xpbXBzZSgpYCBvdXRwdXQuIFRoaXMgbWVhbnMgdGhhdCB0aGUgdmFyaWFibGUgdmFsdWVzIGFyZSBjaGFyYWN0ZXIgc3RyaW5ncywgc3VjaCBhcyB3b3JkcyBvciBwaHJhc2VzLiAKClRoZSBvdGhlciB2YXJpYWJsZXMgYXJlIG9mIGNsYXNzIGA8ZGJsPmAsIHdoaWNoIHN0YW5kcyBmb3IgZG91YmxlIHByZWNpc2lvbiB3aGljaCBpbmRpY2F0ZXMgdGhhdCB0aGUgYXJlIG51bWVyaWMgYW5kIHRoYXQgdGhleSBoYXZlIGRlY2ltYWwgdmFsdWVzLiBJbiBjb250cmFzdCwgb25lIGNvdWxkIGhhdmUgaW50ZWdlciB2YWx1ZXMgd2hpY2ggd291bGQgbm90IGFsbG93IGZvciBkZWNpbWFsIG51bWJlcnMuIEhlcmUgaXMgYSBbbGlua10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRG91YmxlLXByZWNpc2lvbl9mbG9hdGluZy1wb2ludF9mb3JtYXQpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24gb24gZG91YmxlIHByZWNpc2lvbiBudW1lcmljIHZhbHVlcy4KCkFub3RoZXIgY29tbW9uIGRhdGEgY2xhc3MgaXMgZmFjdG9yIHdoaWNoIGlzIGFiYnJldmlhdGVkIGxpa2UgdGhpczogYDxmY3Q+YC4gQSBmYWN0b3IgaXMgc29tZXRoaW5nIHRoYXQgaGFzIHVuaXF1ZSBsZXZlbHMgYnV0IHRoZXJlIGlzIG5vIGFwcHJlY2lhYmxlIG9yZGVyIHRvIHRoZSBsZXZlbHMuIEZvciBleGFtcGxlIHdlIGNhbiBoYXZlIGEgbnVtZXJpYyB2YWx1ZSB0aGF0IGlzIGp1c3QgYW4gaWQgdGhhdCB3ZSB3YW50IHRvIGJlIGludGVycHJldGVkIGFzIGp1c3QgYSB1bmlxdWUgbGV2ZWwgYW5kIG5vdCBhcyB0aGUgbnVtYmVyIHRoYXQgaXQgd291bGQgdHlwaWNhbGx5IGluZGljYXRlLiBUaGlzIHdvdWxkIGJlIHVzZWZ1bCBmb3Igc2V2ZXJhbCBvZiBvdXIgdmFyaWFibGVzOgoKMS4gdGhlIG1vbml0b3IgSUQgKGBpZGApCjIuIHRoZSBGZWRlcmFsIEluZm9ybWF0aW9uIFByb2Nlc3NpbmcgU3RhbmRhcmQgbnVtYmVyIGZvciB0aGUgY291bnR5IHdoZXJlIHRoZSBtb25pdG9yIHdhcyBsb2NhdGVkIChgZmlwc2ApCjMuIHRoZSB6aXAgY29kZSB0YWJ1bGF0aW9uIGFyZWEgKGB6Y3RhYCkKCk5vbmUgb2YgdGhlIHZhbHVlcyBhY3R1YWxseSBoYXZlIGFueSByZWFsIG51bWVyaWMgbWVhbmluZywgc28gd2Ugd2FudCB0byBtYWtlIHN1cmUgdGhhdCBSIGRvZXMgbm90IGludGVycHJldCB0aGVtIGFzIGlmIHRoZXkgZG8uIAoKU28gbGV0J3MgY29udmVydCB0aGVzZSB2YXJpYWJsZXMgaW50byBmYWN0b3JzLiAKV2UgY2FuIGRvIHRoaXMgdXNpbmcgdGhlIGBhY3Jvc3MoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSBhbmQgdGhlIGBhcy5mYWN0b3IoKWAgYmFzZSBmdW5jdGlvbi4gClRoZSBgYWNyb3NzKClgIGZ1bmN0aW9uIGhhcyB0d28gbWFpbiBhcmd1bWVudHM6IChpKSB0aGUgY29sdW1ucyB5b3Ugd2FudCB0byBvcGVyYXRlIG9uIGFuZCAoaWkpIHRoZSBmdW5jdGlvbiBvciBsaXN0IG9mIGZ1bmN0aW9ucyB0byBhcHBseSB0byBlYWNoIGNvbHVtbi4gCgpJbiB0aGlzIGNhc2UsIHdlIGFyZSBhbHNvIHVzaW5nIHRoZSBgbWFncml0dHJgIGFzc2lnbm1lbnQgcGlwZSBvciBkb3VibGUgcGlwZSB0aGF0IGxvb2tzIGxpa2UgdGhpcyBgJTw+JWAgb2YgdGhlIGBtYWdyaXR0cmAgcGFja2FnZS4gClRoaXMgYWxsb3dzIHVzIHVzZSB0aGUgYHBtYCBkYXRhIGFzIGlucHV0LCBidXQgYWxzbyByZWFzc2lnbnMgdGhlIG91dHB1dCB0byB0aGUgc2FtZSBkYXRhIG9iamVjdCBuYW1lLgoKIyMjIyB7LnNjcm9sbGFibGUgfQoKYGBge3J9CiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKcG0gJTw+JQogIG11dGF0ZShhY3Jvc3MoYyhpZCwgZmlwcywgemN0YSksIGFzLmZhY3RvcikpIAoKZ2xpbXBzZShwbSkKYGBgCgojIyMjCgpHcmVhdCEgTm93IHdlIGNhbiBzZWUgdGhhdCB0aGVzZSB2YXJpYWJsZXMgYXJlIG5vdyBmYWN0b3JzIGFzIGluZGljYXRlZCBieSBgPGZjdD5gIGFmdGVyIHRoZSB2YXJpYWJsZSBuYW1lLgoKCgojIyMgU2tpbSBwYWNrYWdlCgpUaGUgYHNraW0oKWAgZnVuY3Rpb24gb2YgdGhlIGBza2ltcmAgcGFja2FnZSBpcyBhbHNvIHJlYWxseSBoZWxwZnVsIGZvciBnZXR0aW5nIGEgZ2VuZXJhbCBzZW5zZSBvZiB5b3VyIGRhdGEuCkJ5IGRlc2lnbiwgaXQgcHJvdmlkZXMgc3VtbWFyeSBzdGF0aXN0aWNzIGFib3V0IHZhcmlhYmxlcyBpbiB0aGUgZGF0YSBzZXQuIAoKCiMjIyMgey5zY3JvbGxhYmxlIH0KCmBgYHtyfQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhCnNraW1yOjpza2ltKHBtKQpgYGAKCiMjIyMKCk5vdGljZSBob3cgdGhlcmUgaXMgYSBjb2x1bW4gY2FsbGVkIGBuX21pc3NpbmdgIGFib3V0IHRoZSBudW1iZXIgb2YgdmFsdWVzIHRoYXQgYXJlIG1pc3NpbmcuIAoKVGhpcyBpcyBhbHNvIGluZGljYXRlZCBieSB0aGUgYGNvbXBsZXRlX3JhdGVgIHZhcmlhYmxlIChvciBtaXNzaW5nL251bWJlciBvZiBvYnNlcnZhdGlvbnMpLiAKCkluIG91ciBkYXRhIHNldCwgaXQgbG9va3MgbGlrZSBvdXIgZGF0YSBkbyBub3QgY29udGFpbiBhbnkgbWlzc2luZyBkYXRhLiAKCkFsc28gbm90aWNlIGhvdyB0aGUgZnVuY3Rpb24gcHJvdmlkZXMgc2VwYXJhdGUgdGFibGVzIG9mIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgZWFjaCBkYXRhIHR5cGU6IGNoYXJhY3RlciwgZmFjdG9yIGFuZCBudW1lcmljLiAKCk5leHQsIHRoZSBgbl91bnFpdWVgIGNvbHVtbiBzaG93cyB1cyB0aGUgbnVtYmVyIG9mIHVuaXF1ZSB2YWx1ZXMgZm9yIGVhY2ggb2Ygb3VyIGNvbHVtbnMuIApXZSBjYW4gc2VlIHRoYXQgdGhlcmUgYXJlIDQ5IHN0YXRlcyByZXByZXNlbnRlZCBpbiB0aGUgZGF0YS4KCldlIGNhbiBzZWUgdGhhdCBmb3IgbWFueSB2YXJpYWJsZXMgdGhlcmUgYXJlIG1hbnkgbG93IHZhbHVlcyBhcyB0aGUgZGlzdHJpYnV0aW9uIHNob3dzIHR3byBwZWFrcywgb25lIG5lYXIgemVybyBhbmQgYW5vdGhlciB3aXRoIGEgaGlnaGVyIHZhbHVlLiAKClRoaXMgaXMgdHJ1ZSBmb3IgdGhlIGBpbXBgIHZhcmlhYmxlcyAobWVhc3VyZXMgb2YgZGV2ZWxvcG1lbnQpLCB0aGUgYG5laWAgdmFyaWFibGVzIChtZWFzdXJlcyBvZiBlbWlzc2lvbiBzb3VyY2VzKSBhbmQgdGhlIHJvYWQgZGVuc2l0eSB2YXJpYWJsZXMuIAoKV2UgY2FuIGFsc28gc2VlIHRoYXQgdGhlIHJhbmdlIG9mIHNvbWUgb2YgdGhlIHZhcmlhYmxlcyBpcyB2ZXJ5IGxhcmdlLCBpbiBwYXJ0aWN1bGFyIHRoZSBhcmVhIGFuZCBwb3B1bGF0aW9uIHJlbGF0ZWQgdmFyaWFibGVzLgoKCkxldCdzIHRha2UgYSBsb29rIHRvIHNlZSB3aGljaCBzdGF0ZXMgYXJlIGluY2x1ZGVkIHVzaW5nIHRoZSBgZGlzdGluY3QoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZToKCmBgYHtyLCBldmFsID0gRkFMU0V9IApwbSAlPiUgCiAgZHBseXI6OmRpc3RpbmN0KHN0YXRlKSAKYGBgCgoKU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dDoKCiMjIyMgey5zY3JvbGxhYmxlIH0KYGBge3IsIGVjaG8gPSBGQUxTRX0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpwbSAlPiUgCiAgZGlzdGluY3Qoc3RhdGUpICU+JQojIHRoaXMgYWxsb3dzIHVzIHRvIHNob3cgdGhlIGZ1bGwgb3V0cHV0IGluIHRoZSByZW5kZXJlZCBybWFya2Rvd24KIHByaW50KG4gPSAxZTMpCmBgYAojIyMjCgpJdCBsb29rcyBsaWtlICJEaXN0cmljdCBvZiBDb2x1bWJpYSIgaXMgYmVpbmcgaW5jbHVkZWQgYXMgYSBzdGF0ZS4gCldlIGNhbiBzZWUgdGhhdCBBbGFza2EgYW5kIEhhd2FpaSBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSBkYXRhLgoKTGV0J3MgYWxzbyB0YWtlIGEgbG9vayB0byBzZWUgaG93IG1hbnkgbW9uaXRvcnMgdGhlcmUgYXJlIGluIGEgZmV3IGNpdGllcy4gV2UgY2FuIHVzZSB0aGUgYGZpbHRlcigpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIHRvIGRvIHNvLiBGb3IgZXhhbXBsZSwgbGV0J3MgbG9vayBhdCBBbGJ1cXVlcnF1ZSwgTmV3IE1leGljby4gCgpgYGB7cn0KcG0gJT4lIGRwbHlyOjpmaWx0ZXIoY2l0eSA9PSAiQWxidXF1ZXJxdWUiKQoKYGBgCgpXZSBjYW4gc2VlIHRoYXQgdGhlcmUgd2VyZSBvbmx5IHR3byBtb25pdG9ycyBpbiB0aGUgY2l0eSBvZiBBbGJ1cXVlcnF1ZSBpbiAyMDA2LiBMZXQncyBjb21wYXJlIHRoaXMgd2l0aCBCYWx0aW1vcmUuCgpgYGB7cn0KcG0gJT4lIGRwbHlyOjpmaWx0ZXIoY2l0eSA9PSAiQmFsdGltb3JlIikKCmBgYAoKVGhlcmUgd2VyZSBpbiBjb250cmFzdCBmaXZlIG1vbml0b3JzIGZvciB0aGUgY2l0eSBvZiBCYWx0aW1vcmUsIGRlc3BpdGUgdGhlIGZhY3QgdGhhdCBpZiB3ZSB0YWtlIGEgbG9vayBhdCB0aGUgbGFuZCBhcmVhIGFuZCBwb3B1bGF0aW9uIG9mIHRoZSBjb3VudGllcyBmb3IgQmxhdGltb3JlIENpdHkgYW5kIEFsYnVxdWVycXVlLCB3ZSBjYW4gc2VlIHRoYXQgdGhleSBoYWQgdmVyeSBzaW1pbGFyIGxhbmQgYXJlYSBhbmQgcG9wdWxhdGlvbnMuCgpgYGB7cn0KcG0gJT4lIAogIGRwbHlyOjpmaWx0ZXIoY2l0eSA9PSAiQmFsdGltb3JlIikgJT4lIAogIHNlbGVjdChjb3VudHlfYXJlYTpjb3VudHlfcG9wKQpwbSAlPiUgCiAgZHBseXI6OmZpbHRlcihjaXR5ID09ICJBbGJ1cXVlcnF1ZSIpICU+JQogIHNlbGVjdChjb3VudHlfYXJlYTpjb3VudHlfcG9wKQoKYGBgCgpJbiBmYWN0LCB0aGUgY291bnR5IGNvbnRhaW5pbmcgQWxidWVycXVlIGhhZCBhIGxhcmdlciBwb3B1bGF0aW9uLiBUaHVzIHRoZSBtZWFzdXJlbWVudHMgZm9yIEFsYnVxdWVycXVlIHdlcmUgbm90IGFzIHRob3JvdWdoIGFzIHRoZXkgd2VyZSBmb3IgQmFsdGltb3JlLgoKVGhpcyBtYXkgYmUgZHVlIHRvIHRoZSBmYWN0IHRoYXQgdGhlIG1vbml0b3IgdmFsdWVzIHdlcmUgbG93ZXIgaW4gQWxidXF1ZXJxdWUuIEl0IGlzIGludGVyZXN0aW5nIHRvIG5vdGUgaGVyZSB0aGF0IHRoZSBDTUFRIHZhbHVlcyBhcmUgcXVpdGUgc2ltaWxhciBmb3IgYm90aCBjaXRpZXMuCgoKIyMgRXZhbHVhdGUgY29ycmVsYXRpb24KCkluIHByZWRpY3Rpb24gYW5hbHlzZXMsIGl0IGlzIGFsc28gdXNlZnVsIHRvIGV2YWx1YXRlIGlmIGFueSBvZiB0aGUgdmFyaWFibGVzIGFyZSBjb3JyZWxhdGVkLiBXaHkgc2hvdWxkIHdlIGNhcmUgYWJvdXQgdGhpcz8KCklmIHdlIGFyZSB1c2luZyBhIGxpbmVhciByZWdyZXNzaW9uIHRvIG1vZGVsIG91ciBkYXRhIHRoZW4gd2UgbWlnaHQgcnVuIGludG8gYSBwcm9ibGVtIGNhbGxlZCBtdWx0aWNvbGluZWFyaXR5IHdoaWNoIGNhbiBsZWFkIHVzIHRvIG1pc2ludGVycHJldCB3aGF0IGlzIHJlYWxseSBwcmVkaWN0aXZlIG9mIG91ciBvdXRjb21lIHZhcmlhYmxlLiBUaGlzIHBoZW5vbWVub24gb2NjdXJzIHdoZW4gdGhlIHByZWRpY3RvciB2YXJpYWJsZXMgYWN0dWFsbHkgcHJlZGljdCBvbmUgYW5vdGhlci4gU2VlIFt0aGlzIGNhc2Ugc3R1ZHldKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pby9vY3MtYnAtUlRDLWFuYWx5c2lzLykgZm9yIGEgZGVlcGVyIGV4cGxhbmF0aW9uIGFib3V0IHRoaXMuIAoKQW5vdGhlciByZWFzb24gd2Ugc2hvdWxkIGxvb2sgb3V0IGZvciBjb3JyZWxhdGlvbiBpcyB0aGF0IHdlIGRvbid0IHdhbnQgdG8gaW5jbHVkZSByZWR1bmRhbnQgdmFyaWFibGVzLiBUaGlzIGNhbiBhZGQgdW5uZWNlc3Nhcnkgbm9pc2UgdG8gb3VyIGFsZ29yaXRobSBjYXVzaW5nIGEgcmVkdWN0aW9uIGluIHByZWRpY3Rpb24gYWNjdXJhY3kgYW5kIGl0IGNhbiBjYXVzZSBvdXIgYWxnb3JpdGhtIHRvIGJlIHVubmVjZXNzYXJpbHkgc2xvd2VyLiBGaW5hbGx5LCBpdCBjYW4gYWxzbyBtYWtlIGl0IGRpZmZpY3VsdCB0byBpbnRlcnByZXQgd2hhdCB2YXJpYWJsZXMgYXJlIGFjdHVhbGx5IHByZWRpY3RpdmUuCgpJbnR1aXRpdmVseSB3ZSBjYW4gZXhwZWN0IHNvbWUgb2Ygb3VyIHZhcmlhYmxlcyB0byBiZSBjb3JyZWxhdGVkLgoKTGV0J3MgZmlyc3QgdGFrZSBhIGxvb2sgYXQgYWxsIG9mIG91ciBudW1lcmljIHZhcmlhYmxlcyB3aXRoIHRoZWBjb3JycGxvdGAgcGFja2FnZToKVGhlIGBjb3JycGxvdGAgcGFja2FnZSBpcyBhbm90aGVyIG9wdGlvbiB0byBsb29rIGF0IGNvcnJlbGF0aW9uIGFtb25nIHBvc3NpYmxlIHByZWRpY3RvcnMsIGFuZCBwYXJ0aWN1bGFybHkgdXNlZnVsIGlmIHdlIGhhdmUgbWFueSBwcmVkaWN0b3JzLiAKCkZpcnN0LCB3ZSBjYWxjdWxhdGUgdGhlIFBlYXJzb24gY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGJldHdlZW4gYWxsIGZlYXR1cmVzIHBhaXJ3aXNlIHVzaW5nIHRoZSBgY29yKClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RhdHNgIHBhY2thZ2UgKHdoaWNoIGlzIGxvYWRlZCBhdXRvbWF0aWNhbGx5KS4gVGhlbiB3ZSB1c2UgdGhlIGBjb3JycGxvdDo6Y29ycnBsb3QoKWAgZnVuY3Rpb24uIAoKYGBge3J9ClBNX2NvciA8LSBjb3IocG0gJT4lIGRwbHlyOjpzZWxlY3RfaWYoaXMubnVtZXJpYykpCmNvcnJwbG90Ojpjb3JycGxvdChQTV9jb3IsIHRsLmNleCA9IDAuNSkKYGBgClRoZSBgdGwuY2V4ID0gMC41YCBhcmd1bWVudCBjb250cm9scyB0aGUgc2l6ZSBvZiB0aGUgdGV4dCBsYWJlbC4gCgpXZSBjYW4gYWxzbyBwbG90IHRoZSBhYnNvbHV0ZSB2YWx1ZSBvZiB0aGUgUGVhcnNvbiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMgdXNpbmcgdGhlIGBhYnMoKWAgZnVuY3Rpb24gZnJvbSBiYXNlIFIgYW5kIGNoYW5nZSB0aGUgb3JkZXIgb2YgdGhlIGNvbHVtbnMuICAKYGBge3J9CmNvcnJwbG90KGFicyhQTV9jb3IpLCBvcmRlciA9ICJoY2x1c3QiLCB0bC5jZXggPSAwLjUsIGNsLmxpbSA9IGMoMCwgMSkpCgpgYGAKClRoZXJlIGFyZSBzZXZlcmFsIG9wdGlvbnMgZm9yIG9yZGVyaW5nIHRoZSB2YXJpYWJsZXMuIFNlZSBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2NvcnJwbG90L3ZpZ25ldHRlcy9jb3JycGxvdC1pbnRyby5odG1sKSBmb3IgbW9yZSBvcHRpb25zLiBIZXJlIHdlIHdpbGwgdXNlIHRoZSAiaGNsdXN0IiBvcHRpb24gZm9yIG9yZGVyaW5nIGJ5IFtoaWVyYXJjaGljYWwgY2x1c3RlcmluZ10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSGllcmFyY2hpY2FsX2NsdXN0ZXJpbmcpIC0gd2hpY2ggd2lsbCBvcmRlciB0aGUgdmFyaWFibGVzIGJ5IGhvdyBzaW1pbGFyIHRoZXkgYXJlIHRvIG9uZSBhbm90aGVyLgoKVGhlIGBjbC5saW0gPSBjKDAsIDEpYCBhcmd1bWVudCBsaW1pdHMgdGhlIGNvbG9yIGxhYmVsIHRvIGJlIGJldHdlZW4gMCBhbmQgMS4gCgoKV2UgY2FuIHNlZSB0aGF0IHRoZSBkZXZlbG9wbWVudCB2YXJpYWJsZXMgKGBpbXBgKSB2YXJpYWJsZXMgYXJlIGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyIGFzIHdlIG1pZ2h0IGV4cGVjdC4gCldlIGFsc28gc2VlIHRoYXQgdGhlIHJvYWQgZGVuc2l0eSB2YXJpYWJsZXMgc2VlbSB0byBiZSBjb3JyZWxhdGVkIHdpdGggZWFjaCBvdGhlciwgYW5kIHRoZSBlbWlzc2lvbiB2YXJpYWJsZXMgc2VlbSB0byBiZSBjb3JyZWxhdGVkIHdpdGggZWFjaCBvdGhlci4gCgoKQWxzbyBub3RpY2UgdGhhdCBub25lIG9mIHRoZSBwcmVkaWN0b3JzIGFyZSBoaWdobHkgY29ycmVsYXRlZCB3aXRoIG91ciBvdXRjb21lIHZhcmlhYmxlIChgdmFsdWVgKS4KCldlIGNhbiB0YWtlIGFsc28gdGFrZSBhIGNsb3NlciBsb29rICB1c2luZyB0aGUgYGdnY29ycigpYCBmdW5jdGlvbiBhbmQgdGhlIGBnZ3BhaXJzKClgIGZ1bmN0aW9uIG9mIHRoZSBgR0dhbGx5YCBwYWNrYWdlLiAKClRvIHNlbGVjdCBvdXIgdmFyaWFibGVzIG9mIGludGVyZXN0IHdlIGNhbiB1c2UgdGhlIGBzZWxlY3QoKWAgZnVuY3Rpb24gd2l0aCB0aGUgYGNvbnRhaW5zKClgIGZ1bmN0aW9uIG9mIHRoZSBgdGlkeXJgIHBhY2thZ2UuIAoKRmlyc3QgbGV0J3MgbG9vayBhdCB0aGUgYGltcGAvZGV2ZWxvcG1lbnQgdmFyaWFibGVzLiAKV2UgY2FuIGNoYW5nZSB0aGUgZGVmYXVsdCBjb2xvciBwYWxldHRlIChgcGFsZXR0ZSA9ICJSZEJ1ImApIGFuZCBhZGQgb24gCmNvcnJlbGF0aW9uIGNvZWZmaWNpZW50cyB0byB0aGUgcGxvdCAoYGxhYmVsID0gVFJVRWApLgoKYGBge3IsIG91dC53aWR0aCA9ICI0MDBweCJ9CnNlbGVjdChwbSwgY29udGFpbnMoImltcCIpKSAlPiUKICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgbGFiZWwgPSBUUlVFKQoKc2VsZWN0KHBtLCBjb250YWlucygiaW1wIikpICU+JQogIGdncGFpcnMoKQpgYGAKCgoKSW5kZWVkLCB3ZSBjYW4gc2VlIHRoYXQgYGltcF9hMTAwMGAgYW5kIGBpbXBfYTUwMGAgYXJlIGhpZ2hseSBjb3JyZWxhdGVkLCBhcyB3ZWxsIGFzIGBpbXBfYTEwMDAwYCwgYGltcF9hMTUwMDBgLgoKTmV4dCwgbGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIHJvYWQgZGVuc2l0eSBkYXRhOgoKYGBge3IsIGZpZy53ZWlnaHQ9MTJ9CnNlbGVjdChwbSwgY29udGFpbnMoInByaSIpKSAlPiUKICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgaGp1c3QgPSAuODUsIHNpemUgPSAzLAogICAgICAgbGF5b3V0LmV4cD0yLCBsYWJlbCA9IFRSVUUpCmBgYAoKV2UgY2FuIHNlZSB0aGF0IG1hbnkgb2YgdGhlIHJvYWQgZGVuc2l0eSB2YXJpYWJsZXMgYXJlIGhpZ2hseSBjb3JyZWxhdGVkIHdpdGggb25lIGFub3RoZXIsIHdoaWxlIG90aGVycyBhcmUgbGVzcyBzby4KCkZpbmFsbHkgbGV0J3MgbG9vayBhdCB0aGUgZW1pc3Npb24gdmFyaWFibGVzLgoKYGBge3J9CnNlbGVjdChwbSwgY29udGFpbnMoIm5laSIpKSAlPiUKICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgaGp1c3QgPSAuODUsIHNpemUgPSAzLAogICAgICAgbGF5b3V0LmV4cD0yLCBsYWJlbCA9IFRSVUUpCgpzZWxlY3QocG0sIGNvbnRhaW5zKCJuZWkiKSkgJT4lCiAgZ2dwYWlycygpCmBgYAoKV2Ugd291bGQgYWxzbyBleHBlY3QgdGhlIHBvcHVsYXRpb24gZGVuc2l0eSBkYXRhIG1pZ2h0IGNvcnJlbGF0ZSB3aXRoIHNvbWUgb2YgdGhlc2UgdmFyaWFibGVzLiAKTGV0J3MgdGFrZSBhIGxvb2suCgpgYGB7cn0KcG0gJT4lCnNlbGVjdChsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDAsIHBvcGRlbnNfY291bnR5LCAKICAgICAgIGxvZ19wcmlfbGVuZ3RoXzEwMDAwLCBpbXBfYTEwMDAwKSAlPiUKICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgIGhqdXN0ID0gLjg1LCBzaXplID0gMywKICAgICAgIGxheW91dC5leHA9MiwgbGFiZWwgPSBUUlVFKQoKcG0gJT4lCnNlbGVjdChsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDAsIHBvcGRlbnNfY291bnR5LCAKICAgICAgIGxvZ19wcmlfbGVuZ3RoXzEwMDAwLCBpbXBfYTEwMDAwLCBjb3VudHlfcG9wKSAlPiUKICBnZ3BhaXJzKCkKYGBgCgoKSW50ZXJlc3RpbmcsIHNvIHRoZXNlIHZhcmlhYmxlcyBkb24ndCBhcHBlYXIgdG8gYmUgaGlnaGx5IGNvcnJlbGF0ZWQsIHRoZXJlZm9yZSB3ZSBtaWdodCBuZWVkIHZhcmlhYmxlcyBmcm9tIGVhY2ggb2YgdGhlIGNhdGVnb3JpZXMgdG8gcHJlZGljdCBvdXIgbW9uaXRvciBQTX4yLjV+IHBvbGx1dGlvbiB2YWx1ZXMuCgpCZWNhdXNlIHNvbWUgdmFyaWFibGVzIGluIG91ciBkYXRhIGhhdmUgZXh0cmVtZSB2YWx1ZXMsIGl0IG1pZ2h0IGJlIGdvb2QgdG8gdGFrZSBhIGxvZyB0cmFuc2Zvcm1hdGlvbi4gVGhpcyBjYW4gYWZmZWN0IG91ciBlc3RpbWF0ZXMgb2YgY29ycmVsYXRpb24uIApgYGB7cn0KcG0gJT4lCiAgbXV0YXRlKGxvZ19wb3BkZW5zX2NvdW50eT0gbG9nKHBvcGRlbnNfY291bnR5KSkgJT4lCnNlbGVjdChsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDAsIGxvZ19wb3BkZW5zX2NvdW50eSwgCiAgICAgICBsb2dfcHJpX2xlbmd0aF8xMDAwMCwgaW1wX2ExMDAwMCkgJT4lCiAgZ2djb3JyKHBhbGV0dGUgPSAiUmRCdSIsICBoanVzdCA9IC44NSwgc2l6ZSA9IDMsCiAgICAgICBsYXlvdXQuZXhwPTIsIGxhYmVsID0gVFJVRSkKCnBtICU+JQogIG11dGF0ZShsb2dfcG9wZGVuc19jb3VudHk9IGxvZyhwb3BkZW5zX2NvdW50eSkpICU+JQogIG11dGF0ZShsb2dfcG9wX2NvdW50eSA9IGxvZyhjb3VudHlfcG9wKSkgJT4lCnNlbGVjdChsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDAsIGxvZ19wb3BkZW5zX2NvdW50eSwgCiAgICAgICBsb2dfcHJpX2xlbmd0aF8xMDAwMCwgaW1wX2ExMDAwMCwgbG9nX3BvcF9jb3VudHkpICU+JQogIGdncGFpcnMoKQpgYGAKCkluZGVlZCB0aGlzIGluY3JlYXNlZCB0aGUgY29ycmVsYXRpb24sIGJ1dCB2YXJpYWJsZXMgZnJvbSBlYWNoIG9mIHRoZXNlIGNhdGVnb3JpZXMgbWF5IHN0aWxsIHByb3ZlIHRvIGJlIHVzZWZ1bCBmb3IgcHJlZGljdGlvbi4KCk5vdyB0aGF0IHdlIGhhdmUgYSBzZW5zZSBvZiB3aGF0IG91ciBkYXRhIGFyZSwgd2UgY2FuIGdldCBzdGFydGVkIHdpdGggYnVpbGRpbmcgYSBtYWNoaW5lIGxlYXJuaW5nIG1vZGVsIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbi4gCgojICoqV2hhdCBpcyBtYWNoaW5lIGxlYXJuaW5nPyoqICB7I3doYXRpc21sfQoqKioKCllvdSBtYXkgaGF2ZSBsZWFybmVkIGFib3V0IHRoZSBjZW50cmFsIGRvZ21hIG9mIHN0YXRpc3RpY3MgdGhhdCB5b3Ugc2FtcGxlIGZyb20gYSBwb3B1bGF0aW9uLgoKIVtdKGltZy9jZGkxLnBuZykKClRoZW4geW91IHVzZSB0aGUgc2FtcGxlIHRvIHRyeSB0byBndWVzcyB3aGF0IGlzIGhhcHBlbmluZyBpbiB0aGUgcG9wdWxhdGlvbi4KCiFbXShpbWcvY2RpMi5wbmcpCgpGb3IgcHJlZGljdGlvbiB3ZSBoYXZlIGEgc2ltaWxhciBzYW1wbGluZyBwcm9ibGVtCgohW10oaW1nL2NkcDEucG5nKQoKQnV0IG5vdyB3ZSBhcmUgdHJ5aW5nIHRvIGJ1aWxkIGEgcnVsZSB0aGF0IGNhbiBiZSB1c2VkIHRvIHByZWRpY3QgYSBzaW5nbGUgb2JzZXJ2YXRpb24ncyB2YWx1ZSBvZiBzb21lIGNoYXJhY3RlcmlzdGljIHVzaW5nIGNoYXJhY3RlcmlzdGljcyBvZiB0aGUgb3RoZXIgb2JzZXJ2YXRpb25zLiAKCiFbXShpbWcvY2RwMi5wbmcpCgpMZXQncyBtYWtlIHRoaXMgbW9yZSBjb25jcmV0ZS4KCklmIHlvdSByZWNhbGwgZnJvbSB0aGUgW1doYXQgYXJlIHRoZSBkYXRhP10oI3doYXRhcmV0aGVkYXRhKSBzZWN0aW9uIGFib3ZlLCB3aGVuIHdlIGFyZSB1c2luZyBtYWNoaW5lIGxlYXJuaW5nIGZvciBwcmVkaWN0aW9uLCBvdXIgZGF0YSBjb25zaXN0cyBvZjogCgoxLiBBbiAqKmNvbnRpbnVvdXMqKiBvdXRjb21lIHZhcmlhYmxlIHRoYXQgd2Ugd2FudCB0byBwcmVkaWN0IAoyLiBBIHNldCBvZiBmZWF0dXJlKHMpIChvciBwcmVkaWN0b3IgdmFyaWFibGVzKSB0aGF0IHdlIHVzZSB0byBwcmVkaWN0IHRoZSBvdXRjb21lIHZhcmlhYmxlCgpXZSB3aWxsIHVzZSAkWSQgdG8gZGVub3RlIHRoZSBvdXRjb21lIHZhcmlhYmxlIGFuZCAkWCA9IChYXzEsIFxkb3RzLCBYX3ApJCB0byBkZW5vdGUgJHAkIGRpZmZlcmVudCBmZWF0dXJlcyAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykuIApCZWNhdXNlIG91ciBvdXRjb21lIHZhcmlhYmxlIGlzICoqY29udGludW91cyoqIChhcyBvcHBvc2VkIHRvIGNhdGVnb3JpY2FsKSwgd2UgYXJlIGludGVyZXN0ZWQgaW4gYSBwYXJ0aWN1bGFyIHR5cGUgb2YgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0uIAoKT3VyIGdvYWwgaXMgdG8gYnVpbGQgYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSB0aGF0IHVzZXMgdGhlIGZlYXR1cmVzICRYJCBhcyBpbnB1dCBhbmQgcHJlZGljdHMgYW4gb3V0Y29tZSB2YXJpYWJsZSAob3IgYWlyIHBvbGx1dGlvbiBsZXZlbHMpIGluIHRoZSBzaXR1YXRpb24gd2hlcmUgd2UgZG8gbm90IGtub3cgdGhlIG91dGNvbWUgdmFyaWFibGUuIAoKVGhlIHdheSB3ZSBkbyB0aGlzIGlzIHRvIHVzZSBkYXRhIHdoZXJlIHdlIGhhdmUgYm90aCB0aGUgZmVhdHVyZXMgJChYXzE9eF8xLCBcZG90cyBYX3A9eF9wKSQgYW5kIHRoZSBhY3R1YWwgb3V0Y29tZSAkWSQgZGF0YSB0byBfdHJhaW5fIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0gdG8gcHJlZGljdCB0aGUgb3V0Y29tZSwgd2hpY2ggd2UgY2FsbCAkXGhhdHtZfSQuICAKCldoZW4gd2Ugc2F5IHRyYWluIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0gd2UgbWVhbiB0aGF0IHdlIGVzdGltYXRlIGEgZnVuY3Rpb24gJGYkIHRoYXQgdXNlcyB0aGUgcHJlZGljdG9yIHZhcmlhYmxlcyAkWCQgYXMgaW5wdXQgb3IgJFxoYXR7WX0gPSBmKFgpJC4gCgojIyBNTCBhcyBhbiBvcHRpbWl6YXRpb24gcHJvYmxlbQoKSWYgd2UgYXJlIGRvaW5nIGEgZ29vZCBqb2IsIHRoZW4gb3VyIHByZWRpY3RlZCBvdXRjb21lICRcaGF0e1l9JCBzaG91bGQgY2xvc2VseSBtYXRjaCBvdXIgYWN0dWFsIG91dGNvbWUgJFkkIHRoYXQgd2Ugb2JzZXJ2ZWQuIAoKSW4gdGhpcyB3YXksIHdlIGNhbiB0aGluayBvZiBtYWNoaW5lIGxlYXJuaW5nIChNTCkgYXMgYW4gb3B0aW1pemF0aW9uIHByb2JsZW0gdGhhdCB0cmllcyB0byBtaW5pbWl6ZSB0aGUgZGlzdGFuY2UgYmV0d2VlbiAkXGhhdHtZfSA9IGYoWCkkIGFuZCAkWSQuIAoKJCRkKFkgLSBmKFgpKSQkClRoZSBjaG9pY2Ugb2YgZGlzdGFuY2UgbWV0cmljICRkKFxjZG90KSQgY2FuIGJlIHRoZSBtZWFuIG9mIHRoZSBhYnNvbHV0ZSBvciBzcXVhcmVkIGRpZmZlcmVuY2Ugb3Igc29tZXRoaW5nIG1vcmUgY29tcGxpY2F0ZWQuIAoKTXVjaCBvZiB0aGUgZmllbGRzIG9mIHN0YXRpc3RpY3MgYW5kIGNvbXB1dGVyIHNjaWVuY2UgYXJlIGZvY3VzZWQgb24gZGVmaW5pbmcgJGYkIGFuZCAkZCQuCgojIyBUaGUgcGFydHMgb2YgYW4gTUwgcHJvYmxlbQoKVG8gc2V0IHVwIGEgbWFjaGluZSBsZWFybmluZyAoTUwpIHByb2JsZW0sIHdlIG5lZWQgYSBmZXcgY29tcG9uZW50cy4KVG8gc29sdmUgYSAoc3RhbmRhcmQpIG1hY2hpbmUgbGVhcm5pbmcgcHJvYmxlbSB5b3UgbmVlZDogCgoxLiBBIGRhdGEgc2V0IHRvIHRyYWluIGZyb20uIAoyLiBBbiBhbGdvcml0aG0gb3Igc2V0IG9mIGFsZ29yaXRobXMgeW91IGNhbiB1c2UgdG8gdHJ5IHZhbHVlcyBvZiAkZiQKMy4gQSBkaXN0YW5jZSBtZXRyaWMgJGQkIGZvciBtZWFzdXJpbmcgaG93IGNsb3NlICRZJCBpcyB0byAkXGhhdHtZfSQKNC4gQSBkZWZpbml0aW9uIG9mIHdoYXQgYSAiZ29vZCIgZGlzdGFuY2UgaXMKCldoaWxlIGVhY2ggb2YgdGhlc2UgY29tcG9uZW50cyBpcyBhIF90ZWNobmljYWxfIHByb2JsZW0sIHRoZXJlIGhhcyBiZWVuIGEgdG9uIG9mIHdvcmsgYWRkcmVzc2luZyB0aG9zZSB0ZWNobmljYWwgZGV0YWlscy4gVGhlIG1vc3QgcHJlc3Npbmcgb3BlbiBpc3N1ZSBpbiBtYWNoaW5lIGxlYXJuaW5nIGlzIHJlYWxpemluZyB0aGF0IHRob3VnaCB0aGVzZSBhcmUgX3RlY2huaWNhbF8gc3RlcHMgdGhleSBhcmUgbm90IF9vYmplY3RpdmVfIHN0ZXBzLiBJbiBvdGhlciB3b3JkcywgaG93IHlvdSBjaG9vc2UgdGhlIGRhdGEsIGFsZ29yaXRobSwgbWV0cmljLCBhbmQgZGVmaW5pdGlvbiBvZiAiZ29vZCIgc2F5cyB3aGF0IHlvdSB2YWx1ZSBhbmQgY2FuIGRyYW1hdGljYWxseSBjaGFuZ2UgdGhlIHJlc3VsdHMuIEEgY291cGxlIG9mIGNhc2VzIHdoZXJlIHRoaXMgd2FzIGEgYmlnIGRlYWwgYXJlOiAKCjEuIFtNYWNoaW5lIGxlYXJuaW5nIGZvciByZWNpZGl2aXNtXShodHRwczovL3d3dy5wcm9wdWJsaWNhLm9yZy9hcnRpY2xlL21hY2hpbmUtYmlhcy1yaXNrLWFzc2Vzc21lbnRzLWluLWNyaW1pbmFsLXNlbnRlbmNpbmcpIC0gcGVvcGxlIGJ1aWx0IE1MIG1vZGVscyB0byBwcmVkaWN0IHdobyB3b3VsZCByZS1jb21taXQgYSBjcmltZS4gQnV0IHRoZXNlIHByZWRpY3Rpb25zIHdlcmUgYmFzZWQgb24gaGlzdG9yaWNhbGx5IGJpYXNlZCBkYXRhIHdoaWNoIGxlZCB0byBiaWFzZWQgcHJlZGljdGlvbnMgYWJvdXQgd2hvIHdvdWxkIGNvbW1pdCBuZXcgY3JpbWVzLiAKMi4gW0RlY2lkaW5nIGhvdyBzZWxmIGRyaXZpbmcgY2FycyBzaG91bGQgYWN0XShodHRwczovL3d3dy5uYXR1cmUuY29tL2FydGljbGVzL2Q0MTU4Ni0wMTgtMDcxMzUtMCkgLSBzZWxmIGRyaXZpbmcgY2FycyB3aWxsIGhhdmUgdG8gbWFrZSBkZWNpc2lvbnMgYWJvdXQgaG93IHRvIGRyaXZlLCB3aG8gdGhleSBtaWdodCBpbmp1cmUsIGFuZCBob3cgdG8gYXZvaWQgYWNjaWRlbnRzLiBEZXBlbmRpbmcgb24gb3VyIGNob2ljZXMgZm9yICRmJCBhbmQgJGQkIHRoZXNlIG1pZ2h0IGxlYWQgdG8gd2lsZGx5IGRpZmZlcmVudCBraW5kcyBvZiBzZWxmIGRyaXZpbmcgY2Fycy4gVHJ5IG91dCB0aGUgW21vcmFsbWFjaGluZV0oaHR0cDovL21vcmFsbWFjaGluZS5taXQuZWR1LykgdG8gc2VlIGhvdyB0aGlzIGxvb2tzIGluIHByYWN0aWNlLiAKCk5vdyB0aGF0IHdlIGtub3cgYSBiaXQgbW9yZSBhYm91dCBtYWNoaW5lIGxlYXJuaW5nLCBsZXQncyBidWlsZCBhIG1vZGVsIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbiBsZXZlbHMgdXNpbmcgdGhlIGB0aWR5bW9kZWxzYCBmcmFtZXdvcmsuIAoKIyAqKk1hY2hpbmUgbGVhcm5pbmcgd2l0aCBgdGlkeW1vZGVsc2AqKgoqKioKVGhlIGdvYWwgaXMgdG8gYnVpbGQgYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSB1c2VzIHRoZSBmZWF0dXJlcyBhcyBpbnB1dCBhbmQgcHJlZGljdHMgYSBvdXRjb21lIHZhcmlhYmxlIChvciBhaXIgcG9sbHV0aW9uIGxldmVscykgaW4gdGhlIHNpdHVhdGlvbiB3aGVyZSB3ZSBkbyBub3Qga25vdyB0aGUgb3V0Y29tZSB2YXJpYWJsZS4gCgpUaGUgd2F5IHdlIGRvIHRoaXMgaXMgdG8gdXNlIGRhdGEgd2hlcmUgd2UgaGF2ZSBib3RoIHRoZSBpbnB1dCBhbmQgb3V0cHV0IGRhdGEgdG8gX3RyYWluXyBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtLiAKClRvIHRyYWluIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0sIHdlIHdpbGwgdXNlIHRoZSBgdGlkeW1vZGVsc2AgcGFja2FnZSBlY29zeXN0ZW0uIAoKIyMgT3ZlcnZpZXcgCgojIyMgVGhlIHRpZHltb2RlbHMgZWNvc3lzdGVtCgpUbyBwZXJmb3JtIG91ciBhbmFseXNpcyB3ZSB3aWxsIGJlIHVzaW5nIHRoZSBgdGlkeW1vZGVsc2Agc3VpdGUgb2YgcGFja2FnZXMuIApZb3UgbWF5IGJlIGZhbWlsaWFyIHdpdGggdGhlIG9sZGVyIHBhY2thZ2VzIGBjYXJldGAgb3IgYG1scmAgd2hpY2ggYXJlIGFsc28gZm9yIG1hY2hpbmUgbGVhcm5pbmcgYW5kIG1vZGVsaW5nIGJ1dCBhcmUgbm90IGEgcGFydCBvZiB0aGUgYHRpZHl2ZXJzZWAuIApbTWF4IEt1aG5dKGh0dHBzOi8vcmVzb3VyY2VzLnJzdHVkaW8uY29tL2F1dGhvcnMvbWF4LWt1aG4pe3RhcmdldD0iX2JsYW5rIn0gZGVzY3JpYmVzIGB0aWR5bW9kZWxzYCBsaWtlIHRoaXM6Cgo+ICJPdGhlciBwYWNrYWdlcywgc3VjaCBhcyBjYXJldCBhbmQgbWxyLCBoZWxwIHRvIHNvbHZlIHRoZSBSIG1vZGVsIEFQSSBpc3N1ZS4gVGhlc2UgcGFja2FnZXMgZG8gYSBsb3Qgb2Ygb3RoZXIgdGhpbmdzIHRvbzogcHJlLXByb2Nlc3NpbmcsIG1vZGVsIHR1bmluZywgcmVzYW1wbGluZywgZmVhdHVyZSBzZWxlY3Rpb24sIGVuc2VtYmxpbmcsIGFuZCBzbyBvbi4gSW4gdGhlIHRpZHl2ZXJzZSwgd2Ugc3RyaXZlIHRvIG1ha2Ugb3VyIHBhY2thZ2VzIG1vZHVsYXIgYW5kIHBhcnNuaXAgaXMgZGVzaWduZWQgb25seSB0byBzb2x2ZSB0aGUgaW50ZXJmYWNlIGlzc3VlLiBJdCBpcyBub3QgZGVzaWduZWQgdG8gYmUgYSBkcm9wLWluIHJlcGxhY2VtZW50IGZvciBjYXJldC4KVGhlIHRpZHltb2RlbHMgcGFja2FnZSBjb2xsZWN0aW9uLCB3aGljaCBpbmNsdWRlcyBwYXJzbmlwLCBoYXMgb3RoZXIgcGFja2FnZXMgZm9yIG1hbnkgb2YgdGhlc2UgdGFza3MsIGFuZCB0aGV5IGFyZSBkZXNpZ25lZCB0byB3b3JrIHRvZ2V0aGVyLiBXZSBhcmUgd29ya2luZyB0b3dhcmRzIGhpZ2hlci1sZXZlbCBBUElzIHRoYXQgY2FuIHJlcGxpY2F0ZSBhbmQgZXh0ZW5kIHdoYXQgdGhlIGN1cnJlbnQgbW9kZWwgcGFja2FnZXMgY2FuIGRvLiIKClRoZXJlIGFyZSBtYW55IFIgcGFja2FnZXMgaW4gdGhlIGB0aWR5bW9kZWxzYCBlY29zeXN0ZW0sIHdoaWNoIGFzc2lzdCB3aXRoIHZhcmlvdXMgc3RlcHMgaW4gdGhlIHByb2Nlc3Mgb2YgYnVpbGRpbmcgYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobS4gVGhlc2UgYXJlIHRoZSBtYWluIHBhY2thZ2VzLCBidXQgdGhlcmUgYXJlIG90aGVycy4KCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwic2ltcGxldGlkeW1vZGVscy5wbmciKSkKYGBgCgpUaGlzIGlzIGEgc2NoZW1hdGljIG9mIGhvdyB0aGVzZSBwYWNrYWdlcyB3b3JrIHRvZ2V0aGVyIHRvIGJ1aWxkIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG06CgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIk1hY2hpbmVMZWFybmluZy5wbmciKSkKYGBgCgojIyMgQmVuZWZpdHMgb2YgdGlkeW1vZGVscyAgCgpUaGUgdHdvIG1ham9yIGJlbmVmaXRzIG9mIGB0aWR5bW9kZWxzYCBhcmU6IAoKMS4gU3RhbmRhcmRpemVkIHdvcmtmbG93L2Zvcm1hdC9ub3RhdGlvbiBhY3Jvc3MgZGlmZmVyZW50IHR5cGVzIG9mIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtcyAgCgpEaWZmZXJlbnQgbm90YXRpb25zIGFyZSByZXF1aXJlZCBmb3IgZGlmZmVyZW50IGFsZ29yaXRobXMgYXMgdGhlIGFsZ29yaXRobXMgaGF2ZSBiZWVuIGRldmVsb3BlZCBieSBkaWZmZXJlbnQgcGVvcGxlLiBUaGlzIHdvdWxkIHJlcXVpcmUgdGhlIHBhaW5zdGFraW5nIHByb2Nlc3Mgb2YgcmVmb3JtYXR0aW5nIHRoZSBkYXRhIHRvIGJlIGNvbXBhdGlibGUgd2l0aCBlYWNoIGFsZ29yaXRobSBpZiBtdWx0aXBsZSBhbGdvcml0aG1zIHdlcmUgdGVzdGVkLgoKMi4gQ2FuIGVhc2lseSBtb2RpZnkgcHJlLXByb2Nlc3NpbmcsIGFsZ29yaXRobSBjaG9pY2UsIGFuZCBoeXBlci1wYXJhbWV0ZXIgdHVuaW5nIG1ha2luZyBvcHRpbWl6YXRpb24gZWFzeSAgCgpNb2RpZnlpbmcgYSBwaWVjZSBvZiB0aGUgb3ZlcmFsbCBwcm9jZXNzIGlzIG5vdyBlYXNpZXIgdGhhbiBiZWZvcmUgYmVjYXVzZSBtYW55IG9mIHRoZSBzdGVwcyBhcmUgc3BlY2lmaWVkIHVzaW5nIHRoZSBgdGlkeW1vZGVsc2AgcGFja2FnZXMgaW4gYSBjb252ZW5pZW50IG1hbm5lci4gVGh1cyB0aGUgZW50aXJlIHByb2Nlc3MgY2FuIGJlIHJlcnVuIGFmdGVyIGEgc2ltcGxlIGNoYW5nZSB0byBwcmUtcHJvY2Vzc2luZyB3aXRob3V0IG11Y2ggZGlmZmljdWx0eS4KCgoKIyMgU3BsaXR0aW5nIHRoZSBkYXRhCgpUaGUgZmlyc3Qgc3RlcCBhZnRlciBkYXRhIGV4cGxvcmF0aW9uIGluIG1hY2hpbmUgbGVhcm5pbmcgYW5hbHlzaXMgaXMgdG8gW3NwbGl0IHRoZSBkYXRhXShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vdHJhaW4tdmFsaWRhdGlvbi1hbmQtdGVzdC1zZXRzLTcyY2I0MGNiYTllNyl7dGFyZ2V0PSJfYmxhbmsifSBpbnRvICoqdHJhaW5pbmcqKiBhbmQgKip0ZXN0aW5nKiogZGF0YSBzZXRzLiAKClRoZSB0cmFpbmluZyBkYXRhIHNldCB3aWxsIGJlIHVzZWQgdG8gYnVpbGQgYW5kIHR1bmUgb3VyIG1vZGVsLiAKVGhpcyBpcyB0aGUgZGF0YSB0aGF0IHRoZSBtb2RlbCAibGVhcm5zIiBvbi4gClRoZSB0ZXN0aW5nIGRhdGEgc2V0IHdpbGwgYmUgdXNlZCB0byBldmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2Ygb3VyIG1vZGVsIGluIGEgbW9yZSBnZW5lcmFsaXphYmxlIHdheS4gV2hhdCBkbyB3ZSBtZWFuIGJ5ICJnZW5lcmFsaXphYmxlIj8KClJlbWVtYmVyIHRoYXQgb3VyIG1haW4gZ29hbCBpcyB0byB1c2Ugb3VyIG1vZGVsIHRvIGJlIGFibGUgdG8gcHJlZGljdCBhaXIgcG9sbHV0aW9uIGxldmVscyBpbiBhcmVhcyB3aGVyZSB0aGVyZSBhcmUgbm8gZ3JhdmltZXRyaWMgbW9uaXRvcnMuIAoKVGhlcmVmb3JlLCBpZiBvdXIgbW9kZWwgaXMgcmVhbGx5IGdvb2QgYXQgcHJlZGljdGluZyBhaXIgcG9sbHV0aW9uIHdpdGggdGhlIGRhdGEgdGhhdCB3ZSB1c2UgdG8gYnVpbGQgaXQsIGl0IG1pZ2h0IG5vdCBkbyB0aGUgYmVzdCBqb2IgZm9yIHRoZSBhcmVhcyB3aGVyZSB0aGVyZSBhcmUgZmV3IHRvIG5vIG1vbml0b3JzLiAKClRoaXMgd291bGQgY2F1c2UgdXMgdG8gaGF2ZSByZWFsbHkgZ29vZCBwcmVkaWN0aW9uIGFjY3VyYWN5IGFuZCB3ZSBtaWdodCBhc3N1bWUgdGhhdCB3ZSB3ZXJlIGdvaW5nIHRvIGRvIGEgZ29vZCBqb2IgZXN0aW1hdGluZyBhaXIgcG9sbHV0aW9uIGFueSB0aW1lIHdlIHVzZSBvdXIgbW9kZWwsIGJ1dCBpbiBmYWN0IHRoaXMgd291bGQgbGlrZWx5IG5vdCBiZSB0aGUgY2FzZS4gClRoaXMgc2l0dWF0aW9uIGlzIHdoYXQgd2UgY2FsbCAqKltvdmVyZml0dGluZ10oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL3RyYWluLXRlc3Qtc3BsaXQtYW5kLWNyb3NzLXZhbGlkYXRpb24taW4tcHl0aG9uLTgwYjYxYmVjYTRiNil7dGFyZ2V0PSJfYmxhbmsifSAqKi4KCk92ZXJmaXR0aW5nIGhhcHBlbnMgd2hlbiB3ZSBlbmQgdXAgbW9kZWxpbmcgbm90IG9ubHkgdGhlIG1ham9yIHJlbGF0aW9uc2hpcHMgaW4gb3VyIGRhdGEgYnV0IGFsc28gdGhlIG5vaXNlIHdpdGhpbiBvdXIgZGF0YS4gCgpgYGB7ciwgZWNobz1GQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vbWlyby5tZWRpdW0uY29tL21heC8xMTEwLzEqdEJFclhZVnZUdzJqU1VZSzd0aFUyQS5wbmciKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9taXJvLm1lZGl1bS5jb20vbWF4LzExMTAvMSp0QkVyWFlWdlR3MmpTVVlLN3RoVTJBLnBuZyl7dGFyZ2V0PSJfYmxhbmsifQoKSWYgd2UgZ2V0IGdvb2QgcHJlZGljdGlvbiB3aXRoIG91ciB0ZXN0aW5nIHNldCwgdGhlbiB3ZSBrbm93IHRoYXQgb3VyIG1vZGVsIGNhbiBiZSBhcHBsaWVkIHRvIG90aGVyIGRhdGEgYW5kIHdpbGwgbGlrZWx5IHBlcmZvcm0gd2VsbC4gV2Ugd2lsbCBkaXNjdXNzIHRoaXMgbW9yZSBsYXRlci4KCldlIHdpbGwgbm90IHRvdWNoIHRoZSB0ZXN0aW5nIHNldCB1bnRpbCB3ZSBoYXZlIGNvbXBsZXRlZCBvcHRpbWl6aW5nIG91ciBtb2RlbCB3aXRoIHRoZSB0cmFpbmluZyBzZXQuIApUaGlzIHdpbGwgYWxsb3cgdXMgdG8gaGF2ZSBhIGxlc3MgYmlhc2VkIGV2YWx1YXRpb24gb2YgaG93IHdlbGwgb3VyIG1vZGVsIGNhbiBkbyB3aXRoIG90aGVyIGRhdGEgYmVzaWRlcyB0aGUgZGF0YSB1c2VkIGluIHRoZSB0cmFpbmluZyBzZXQgdG8gYnVpbGQgdGhlIG1vZGVsLiAKSWRlYWxseSwgeW91IHdvdWxkIGFsc28gd2FudCBhIGNvbXBsZXRlbHkgaW5kZXBlbmRlbnQgZGF0YSBzZXQgdG8gZnVydGhlciB0ZXN0IHRoZSBwZXJmb3JtYW5jZSBvZiB5b3VyIG1vZGVsLgoKVG8gc3BsaXQgdGhlIGRhdGEgaW50byB0cmFpbmluZyBhbmQgdGVzdGluZywgd2Ugd2lsbCB1c2UgdGhlIGBpbml0aWFsX3NwbGl0KClgIGZ1bmN0aW9uIGluIHRoZSBgcnNhbXBsZWAgcGFja2FnZSB0byBzcGVjaWZ5IGhvdyB3ZSB3YW50IHRvIHNwbGl0IG91ciBkYXRhLgoKCmBgYHtyLCBlY2hvPUZBTFNFfQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwic3BsaXQucG5nIikpCmBgYAoKYGBge3J9CnNldC5zZWVkKDEyMzQpCnBtX3NwbGl0IDwtIHJzYW1wbGU6OmluaXRpYWxfc3BsaXQoZGF0YSA9IHBtLCBwcm9wID0gMi8zKQpwbV9zcGxpdApgYGAKCkEgY291cGxlIG9mIG5vdGVzIGZyb20gdGhlIGNvZGUgYWJvdmU6IAoKLSBUeXBpY2FsbHksIGRhdGEgYXJlIHNwbGl0IGludG8gMy80IG9mIHRoZSBvYnNlcnZhdGlvbnMgZm9yIHRyYWluaW5nIGFuZCAxLzQgZm9yIHRlc3RpbmcuIFRoaXMgaXMgdGhlIGRlZmF1bHQgcHJvcG9ydGlvbiBhbmQgZG9lcyBub3QgbmVlZCB0byBiZSBzcGVjaWZpZWQuIEhvd2V2ZXIsIHlvdSBjYW4gY2hhbmdlIHRoZSBwcm9wb3J0aW9uIHVzaW5nIHRoZSBgcHJvcGAgYXJndW1lbnQsIHdoaWNoIHdlIHdpbGwgZG8gdGhhdCBoZXJlIGZvciBpbGx1c3RyYXRpdmUgcHVycG9zZXMuCi0gU2luY2UgdGhlIHNwbGl0IGlzIHBlcmZvcm1lZCByYW5kb21seSwgaXQgaXMgYSBnb29kIGlkZWEgdG8gdXNlIHRoZSBgc2V0LnNlZWQoKWAgZnVuY3Rpb24gaW4gYmFzZSBSIHRvIGVuc3VyZSB0aGF0IGlmIHlvdXIgcmVydW4geW91ciBjb2RlIHRoYXQgeW91ciBzcGxpdCB3aWxsIGJlIHRoZSBzYW1lIG5leHQgdGltZS4KLSBXZSBjYW4gc2VlIHRoZSBudW1iZXIgb2YgbW9uaXRvcnMgaW4gb3VyIHRyYWluaW5nLCB0ZXN0aW5nLCBhbmQgb3JpZ2luYWwgZGF0YSBieSB0eXBpbmcgaW4gdGhlIG5hbWUgb2Ygb3VyIHNwbGl0IG9iamVjdC4gVGhlIHJlc3VsdCB3aWxsIGxvb2sgbGlrZSB0aGlzOgo8dHJhaW5pbmcgZGF0YSBzYW1wbGUgbnVtYmVyLCB0ZXN0aW5nIGRhdGEgc2FtcGxlIG51bWJlciwgb3JpZ2luYWwgc2FtcGxlIG51bWJlcj4gCgpOb3csIHlvdSBjYW4gYWxzbyBzcGVjaWZ5IGEgdmFyaWFibGUgdG8gc3RyYXRpZnkgYnkgd2l0aCB0aGUgYHN0cmF0YWAgYXJndW1lbnQuIApUaGlzIGlzIHVzZWZ1bCBpZiB5b3UgaGF2ZSBpbWJhbGFuY2VkIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhbmQgeW91IHdvdWxkIGxpa2UgdG8gaW50ZW50aW9uYWxseSBtYWtlIHN1cmUgdGhhdCB0aGVyZSBhcmUgc2ltaWxhciBudW1iZXIgb2Ygc2FtcGxlcyBvZiB0aGUgcmFyZXIgY2F0ZWdvcmllcyBpbiBib3RoIHRoZSB0ZXN0aW5nIGFuZCB0cmFpbmluZyBzZXRzLiAKT3RoZXJ3aXNlIHRoZSBzcGxpdCBpcyBwZXJmb3JtZWQgcmFuZG9tbHkuIAoKQWNjb3JkaW5nIHRvIHRoZSBbZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL3JzYW1wbGUvdmVyc2lvbnMvMC4wLjUvdG9waWNzL2luaXRpYWxfc3BsaXQpIGZvciB0aGUgYHJzYW1wbGVgIHBhY2thZ2U6Cgo+IFRoZSBzdHJhdGEgYXJndW1lbnQgY2F1c2VzIHRoZSByYW5kb20gc2FtcGxpbmcgdG8gYmUgY29uZHVjdGVkIHdpdGhpbiB0aGUgc3RyYXRpZmljYXRpb24gdmFyaWFibGUuIFRoaXMgY2FuIGhlbHAgZW5zdXJlIHRoYXQgdGhlIG51bWJlciBvZiBkYXRhIHBvaW50cyBpbiB0aGUgdHJhaW5pbmcgZGF0YSBpcyBlcXVpdmFsZW50IHRvIHRoZSBwcm9wb3J0aW9ucyBpbiB0aGUgb3JpZ2luYWwgZGF0YSBzZXQuCgpJbiB0aGUgY2FzZSB3aXRoIG91ciBkYXRhIHNldCwgcGVyaGFwcyB3ZSB3b3VsZCBsaWtlIG91ciB0cmFpbmluZyBzZXQgdG8gaGF2ZSBzaW1pbGFyIHByb3BvcnRpb25zIG9mIG1vbml0b3JzIGZyb20gZWFjaCBvZiB0aGUgc3RhdGVzIGFzIGluIHRoZSBpbml0aWFsIGRhdGEuIApUaGlzIG1pZ2h0IGJlIHVzZWZ1bCBpZiB3ZSB3YW50IG91ciBtb2RlbCB0byBiZSBnZW5lcmFsaXphYmxlIGFjcm9zcyBhbGwgb2YgdGhlIHN0YXRlcy4KCldlIGNhbiBzZWUgdGhhdCBpbmRlZWQgdGhlcmUgYXJlIGRpZmZlcmVudCBwcm9wb3J0aW9ucyBvZiBtb25pdG9ycyBpbiBlYWNoIHN0YXRlIGJ5IHVzaW5nIHRoZSBgY291bnQoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4gCgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpjb3VudChwbSwgc3RhdGUpCmBgYAoKU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dDoKCiMjIyMgey5zY3JvbGxhYmxlIH0KCmBgYHtyLCBlY2hvPUZBTFNFfQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhCmNvdW50KHBtLCBzdGF0ZSkgJT4lCiAgcHJpbnQobiA9IDFlMykKYGBgCiMjIyMKCklmIG91ciBkYXRhIHNldCB3ZXJlIGxhcmdlIGVub3VnaCBpdCBtaWdodCBiZSBuaWNlIHRoZW4gdG8gc3RyYXRpZnkgYnkgc3RhdGUgdXNpbmcgdGhlIGBzdHJhdGEgPSAic3RhdGUiYCBhcmd1bWVudCBpbiBgaW5pdGlhbF9zcGxpdCgpYCwgYnV0IG91ciBkYXRhIGlzIHVuZm9ydHVuYXRlbHkgbm90IGxhcmdlIGVub3VnaC4gCgpJbXBvcnRhbnRseSB0aGUgYGluaXRpYWxfc3BsaXQoKWAgZnVuY3Rpb24gb25seSBkZXRlcm1pbmVzIHdoYXQgcm93cyBvZiBvdXIgYHBtYCBkYXRhIGZyYW1lIHNob3VsZCBiZSBhc3NpZ25lZCBmb3IgdHJhaW5pbmcgb3IgdGVzdGluZywgaXQgZG9lcyBub3QgYWN0dWFsbHkgc3BsaXQgdGhlIGRhdGEuIAoKVG8gZXh0cmFjdCB0aGUgdGVzdGluZyBhbmQgdHJhaW5pbmcgZGF0YSB3ZSBjYW4gdXNlIHRoZSBgdHJhaW5pbmcoKWAgYW5kIGB0ZXN0aW5nKClgIGZ1bmN0aW9ucyBhbHNvIG9mIHRoZSBgcnNhbXBsZWAgcGFja2FnZS4KCiMjIyMgey5zY3JvbGxhYmxlIH0KYGBge3J9CnRyYWluX3BtIDwtcnNhbXBsZTo6dHJhaW5pbmcocG1fc3BsaXQpCnRlc3RfcG0gPC1yc2FtcGxlOjp0ZXN0aW5nKHBtX3NwbGl0KQogCiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKY291bnQodHJhaW5fcG0sIHN0YXRlKQpjb3VudCh0ZXN0X3BtLCBzdGF0ZSkKYGBgCiMjIyMKCgoKIyMgUHJlcGFyaW5nIGZvciBwcmUtcHJvY2Vzc2luZyB0aGUgZGF0YQoKQWZ0ZXIgc3BsaXR0aW5nIHRoZSBkYXRhLCB0aGUgbmV4dCBzdGVwIGlzIHRvIHByb2Nlc3MgdGhlIHRyYWluaW5nIGFuZCB0ZXN0aW5nIGRhdGEgc28gdGhhdCB0aGUgZGF0YSBhcmUgYXJlIGNvbXBhdGlibGUgYW5kIG9wdGltaXplZCB0byBiZSB1c2VkIHdpdGggdGhlIG1vZGVsLiAKVGhpcyBpbnZvbHZlcyBhc3NpZ25pbmcgdmFyaWFibGVzIHRvIHNwZWNpZmljIHJvbGVzIHdpdGhpbiB0aGUgbW9kZWwgYW5kIHByZS1wcm9jZXNzaW5nIGxpa2Ugc2NhbGluZyB2YXJpYWJsZXMgYW5kIHJlbW92aW5nIHJlZHVuZGFudCB2YXJpYWJsZXMuIApUaGlzIHByb2Nlc3MgaXMgYWxzbyBjYWxsZWQgZmVhdHVyZSBlbmdpbmVlcmluZy4KClRvIGRvIHRoaXMgaW4gYHRpZHltb2RlbHNgLCB3ZSB3aWxsIGNyZWF0ZSB3aGF0J3MgY2FsbGVkIGEgInJlY2lwZSIgdXNpbmcgdGhlIGByZWNpcGVzYCBwYWNrYWdlLCB3aGljaCBpcyBhIHN0YW5kYXJkaXplZCBmb3JtYXQgZm9yIGEgc2VxdWVuY2Ugb2Ygc3RlcHMgZm9yIHByZS1wcm9jZXNzaW5nIHRoZSBkYXRhLgpUaGlzIGNhbiBiZSB2ZXJ5IHVzZWZ1bCBiZWNhdXNlIGl0IG1ha2VzIHRlc3Rpbmcgb3V0IGRpZmZlcmVudCBwcmUtcHJvY2Vzc2luZyBzdGVwcyBvciBkaWZmZXJlbnQgYWxnb3JpdGhtcyB3aXRoIHRoZSBzYW1lIHByZS1wcm9jZXNzaW5nIHZlcnkgZWFzeSBhbmQgcmVwcm9kdWNpYmxlLgpDcmVhdGluZyBhIHJlY2lwZSBzcGVjaWZpZXMgKipob3cgYSBkYXRhIGZyYW1lIG9mIHByZWRpY3RvcnMgc2hvdWxkIGJlIGNyZWF0ZWQqKiAtIGl0IHNwZWNpZmllcyB3aGF0IHZhcmlhYmxlcyB0byBiZSB1c2VkIGFuZCB0aGUgcHJlLXByb2Nlc3Npbmcgc3RlcHMsIGJ1dCBpdCAqKmRvZXMgbm90IGV4ZWN1dGUgdGhlc2Ugc3RlcHMqKiBvciBjcmVhdGUgdGhlIGRhdGEgZnJhbWUgb2YgcHJlZGljdG9ycy4KCiMjIyBTdGVwIDE6IFNwZWNpZnkgdmFyaWFibGVzIHJvbGVzIHdpdGggYHJlY2lwZSgpYCBmdW5jdGlvbgoKVGhlIGZpcnN0IHRoaW5nIHRvIGRvIHRvIGNyZWF0ZSBhIHJlY2lwZSBpcyB0byBzcGVjaWZ5IHdoaWNoIHZhcmlhYmxlcyB3ZSB3aWxsIGJlIHVzaW5nIGFzIG91ciBvdXRjb21lIGFuZCBwcmVkaWN0b3JzIHVzaW5nIHRoZSBgcmVjaXBlKClgIGZ1bmN0aW9uLiAKSW4gdGVybXMgb2YgdGhlIG1ldGFwaG9yIG9mIGJha2luZywgd2UgY2FuIHRoaW5rIG9mIHRoaXMgYXMgbGlzdGluZyBvdXIgaW5ncmVkaWVudHMuIApUcmFuc2xhdGluZyB0aGlzIHRvIHRoZSBgcmVjaXBlc2AgcGFja2FnZSwgd2UgdXNlIHRoZSBgcmVjaXBlKClgIGZ1bmN0aW9uIHRvIGFzc2lnbiByb2xlcyB0byBhbGwgdGhlIHZhcmlhYmxlcy4gCgpMZXQncyB0cnkgdGhlIHNpbXBsZXN0IHJlY2lwZSB3aXRoIG5vIHByZS1wcm9jZXNzaW5nIHN0ZXBzOiBzaW1wbHkgbGlzdCB0aGUgb3V0Y29tZSBhbmQgcHJlZGljdG9yIHZhcmlhYmxlcy4KCldlIGNhbiBkbyBzbyBpbiB0d28gd2F5czogIAoKMSkgVXNpbmcgZm9ybXVsYSBub3RhdGlvbiAgCjIpIEFzc2lnbmluZyByb2xlcyB0byBlYWNoIHZhcmlhYmxlICAKCkxldCdzIGxvb2sgYXQgdGhlIGZpcnN0IHdheSB1c2luZyBmb3JtdWxhIG5vdGF0aW9uLCB3aGljaCBsb29rcyBsaWtlIHRoaXM6ICAKCm91dGNvbWUocykgfiBwcmVkaWN0b3IocykgIAoKSWYgaW4gdGhlIGNhc2Ugb2YgbXVsdGlwbGUgcHJlZGljdG9ycyBvciBhIG11bHRpdmFyaWF0ZSBzaXR1YXRpb24gd2l0aCB0d28gb3V0Y29tZXMsIHVzZSBhIHBsdXMgc2lnbjogIAoKb3V0Y29tZTEgKyBvdXRjb21lMiB+IHByZWRpY3RvcjEgKyBwcmVkaWN0b3IyICAKCklmIHdlIHdhbnQgdG8gaW5jbHVkZSBhbGwgcHJlZGljdG9ycyB3ZSBjYW4gdXNlIGEgcGVyaW9kIGxpa2Ugc286ICAKCm91dGNvbWVfdmFyaWFibGVfbmFtZSB+IC4gIAoKTm93IHdpdGggb3VyIGRhdGEsIHdlIHdpbGwgc3RhcnQgYnkgbWFraW5nIGEgcmVjaXBlIGZvciBvdXIgdHJhaW5pbmcgZGF0YS4KSWYgeW91IHJlY2FsbCwgdGhlIGNvbnRpbnVvdXMgb3V0Y29tZSB2YXJpYWJsZSBpcyBgdmFsdWVgICh0aGUgYXZlcmFnZSBhbm51YWwgZ3JhdmltZXRyaWMgbW9uaXRvciBQTX4yLjV+IGNvbmNlbnRyYXRpb24gaW4gdWcvbV4zXikuIApPdXIgZmVhdHVyZXMgKG9yIHByZWRpY3RvciB2YXJpYWJsZXMpIGFyZSBhbGwgdGhlIG90aGVyIHZhcmlhYmxlcyBleGNlcHQgdGhlIG1vbml0b3IgSUQsIHdoaWNoIGlzIGFuIGBpZGAgdmFyaWFibGUuCgpUaGUgcmVhc29uIG5vdCB0byBpbmNsdWRlIHRoZSBgaWRgIHZhcmlhYmxlIGlzIGJlY2F1c2UgdGhpcyB2YXJpYWJsZSBpbmNsdWRlcyB0aGUgY291bnR5IG51bWJlciBhbmQgYSBudW1iZXIgZGVzaWduYXRpbmcgd2hpY2ggcGFydGljdWxhciBtb25pdG9yIHRoZSB2YWx1ZXMgY2FtZSBmcm9tIChvZiB0aGUgbW9uaXRvcnMgdGhlcmUgYXJlIGluIHRoYXQgY291bnR5KS4gClNpbmNlIHRoaXMgbnVtYmVyIGlzIGFyYml0cmFyeSBhbmQgdGhlIGNvdW50eSBpbmZvcm1hdGlvbiBpcyBhbHNvIGdpdmVuIGluIHRoZSBkYXRhLCBhbmQgdGhlIGZhY3QgdGhhdCBlYWNoIG1vbml0b3Igb25seSBoYXMgb25lIHZhbHVlIGluIHRoZSBgdmFsdWVgIHZhcmlhYmxlLCBub3RoaW5nIGlzIGdhaW5lZCBieSBpbmNsdWRpbmcgdGhpcyB2YXJpYWJsZSBhbmQgaXQgbWF5IGluc3RlYWQgaW50cm9kdWNlIG5vaXNlLiAKSG93ZXZlciwgaXQgaXMgdXNlZnVsIHRvIGtlZXAgdGhpcyBkYXRhIHRvIHRha2UgYSBsb29rIGF0IHdoYXQgaXMgaGFwcGVuaW5nIGxhdGVyLiAKV2Ugd2lsbCBzaG93IHlvdSB3aGF0IHRvIGRvIGluIHRoaXMgY2FzZSBpbiBqdXN0IGEgYml0LgoKSW4gdGhlIHNpbXBsZXN0IGNhc2UsIHdlIG1pZ2h0IHVzZSBhbGwgcHJlZGljdG9ycyBsaWtlIHRoaXM6CgpgYGB7cn0Kc2ltcGxlX3JlYyA8LSB0cmFpbl9wbSAlPiUKICByZWNpcGVzOjpyZWNpcGUodmFsdWUgfiAuKQoKc2ltcGxlX3JlYwpgYGAKCldlIHNlZSBhIHJlY2lwZSBoYXMgYmVlbiBjcmVhdGVkIHdpdGggMSBvdXRjb21lIHZhcmlhYmxlIGFuZCA0OSBwcmVkaWN0b3IgdmFyaWFibGVzIChvciBmZWF0dXJlcykuIApBbHNvLCBub3RpY2UgaG93IHdlIG5hbWVkIHRoZSBvdXRwdXQgb2YgYHJlY2lwZSgpYC4gClRoZSBuYW1pbmcgY29udmVudGlvbiBmb3IgcmVjaXBlIG9iamVjdHMgaXMgYCpfcmVjYCBvciBgcmVjYC4gCgpOb3csIGxldCdzIGdldCBiYWNrIHRvIHRoZSBgaWRgIHZhcmlhYmxlLiAKSW5zdGVhZCBvZiBpbmNsdWRpbmcgaXQgYXMgYSBwcmVkaWN0b3IgdmFyaWFibGUsIHdlIGNvdWxkIGFsc28gdXNlIHRoZSBgdXBkYXRlX3JvbGUoKWAgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlLgoKYGBge3J9CnNpbXBsZV9yZWMgPC0gdHJhaW5fcG0gJT4lCiAgcmVjaXBlczo6cmVjaXBlKHZhbHVlIH4gLikgJT4lCiAgcmVjaXBlczo6dXBkYXRlX3JvbGUoaWQsIG5ld19yb2xlID0gImlkIHZhcmlhYmxlIikKCnNpbXBsZV9yZWMKYGBgCgo8ZGV0YWlscz48c3VtbWFyeT4gQ2xpY2sgaGVyZSBsZWFybiBtb3JlIGFib3V0IHRoZSB3b3JraW5nIHdpdGggYGlkYCB2YXJpYWJsZXMgPC9zdW1tYXJ5PgoKVGhpcyBvcHRpb24gd29ya3Mgd2VsbCB3aXRoIHRoZSBuZXdlciBgd29ya2Zsb3dzYCBwYWNrYWdlLCBob3dldmVyIGBpZGAgdmFyaWFibGVzIGFyZSBvZnRlbiBkcm9wcGVkIGZyb20gYW5hbHlzZXMgdGhhdCBkbyBub3QgdXNlIHRoaXMgbmV3ZXIgcGFja2FnZSBhcyB0aGV5IGNhbiBtYWtlIHRoZSBwcm9jZXNzIGRpZmZpY3VsdCB3aXRoIHVzaW5nIHRoZSBgcGFyc25pcGAgcGFja2FnZSBhbG9uZSBkdWUgdG8gdGhlIGZhY3QgdGhhdCBuZXcgbGV2ZWxzIChvciBwb3NzaWJsZSB2YWx1ZXMpIG1heSBiZSBpbnRyb2R1Y2VkIHdpdGggdGhlIHRlc3RpbmcgZGF0YS4KCjwvZGV0YWlscz4KCldlIGNvdWxkIGFsc28gc3BlY2lmeSB0aGUgb3V0Y29tZSBhbmQgcHJlZGljdG9ycyBpbiB0aGUgc2FtZSB3YXkgYXMgd2UganVzdCBzcGVjaWZpZWQgdGhlIGlkIHZhcmlhYmxlLiAKUGxlYXNlIHNlZSBbaGVyZV0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yZWNpcGVzL3JlZmVyZW5jZS9yZWNpcGUuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgZXhhbXBsZXMgb2Ygb3RoZXIgcm9sZXMgZm9yIHZhcmlhYmxlcy4gClRoZSByb2xlIGNhbiBiZSBhY3R1YWxseSBiZSBhbnkgdmFsdWUuIAoKVGhlIG9yZGVyIGlzIGltcG9ydGFudCBoZXJlLCBhcyB3ZSBmaXJzdCBtYWtlIGFsbCB2YXJpYWJsZXMgcHJlZGljdG9ycyBhbmQgdGhlbiBvdmVycmlkZSB0aGlzIHJvbGUgZm9yIHRoZSBvdXRjb21lIGFuZCBgaWRgIHZhcmlhYmxlLiAKV2Ugd2lsbCB1c2UgdGhlIGBldmVyeXRoaW5nKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gc3RhcnQgd2l0aCBhbGwgb2YgdGhlIHZhcmlhYmxlcyBpbiBgdHJhaW5fcG1gLgoKYGBge3J9CnNpbXBsZV9yZWMgPC1yZWNpcGUodHJhaW5fcG0pICU+JQogICAgdXBkYXRlX3JvbGUoZXZlcnl0aGluZygpLCBuZXdfcm9sZSA9ICJwcmVkaWN0b3IiKSU+JQogICAgdXBkYXRlX3JvbGUodmFsdWUsIG5ld19yb2xlID0gIm91dGNvbWUiKSU+JQogICAgdXBkYXRlX3JvbGUoaWQsIG5ld19yb2xlID0gImlkIHZhcmlhYmxlIikKCnNpbXBsZV9yZWMKYGBgCgpJZiB3ZSB3YW50IHRvIHRha2UgYSBsb29rIGF0IG91ciBmb3JtdWxhIGZyb20gb3VyIHJlY2lwZSwgd2UgY2FuIGRvIHVzZSB0aGUgYGZvcm11bGEoKWAgZnVuY3Rpb24gb2YgdGhlIGBzdGF0c2AgcGFja2FnZS4KCmBgYHtyfQpmb3JtdWxhKHNpbXBsZV9yZWMpCmBgYAoKV2UgY2FuIGFsc28gdmlldyBvdXIgcmVjaXBlIGluIG1vcmUgZGV0YWlsIHVzaW5nIHRoZSBiYXNlIGBzdW1tYXJ5KClgIGZ1bmN0aW9uLgoKYGBge3J9CnN1bW1hcnkoc2ltcGxlX3JlYykKYGBgCgpUbyBzdW1tYXJpemUgdGhpcyBzdGVwLCB3ZSB1c2UgdGhlIGByZWNpcGUoKWAgZnVuY3Rpb24gdG8gYXNzaWduIHJvbGVzIHRvIGFsbCB0aGUgdmFyaWFibGVzOiAKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjQwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiU3RhcnRpbmdfYV9yZWNpcGVfcmVjaXBlczEucG5nIikpCmBgYAoKCiMjIyBTdGVwIDI6IFNwZWNpZnkgdGhlIHByZS1wcm9jZXNzaW5nIHN0ZXBzIHdpdGggYHN0ZXAqKClgIGZ1bmN0aW9ucwoKTmV4dCwgd2UgdXNlIHRoZSBgc3RlcCooKWAgZnVuY3Rpb25zIGZyb20gdGhlIGByZWNpcGVgIHBhY2thZ2UgdG8gc3BlY2lmeSBwcmUtcHJvY2Vzc2luZyBzdGVwcy4gCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI0MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIk1ha2luZ19hX3JlY2lwZV9yZWNpcGVzMi5wbmciKSkKYGBgCgoqKlRoaXMgW2xpbmtdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcmVjaXBlcy9yZWZlcmVuY2UvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBhbmQgdGhpcyBbbGlua10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JlY2lwZXMvcmVjaXBlcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gc2hvdyB0aGUgbWFueSBvcHRpb25zIGZvciByZWNpcGUgc3RlcCBmdW5jdGlvbnMuKioKCjx1PlRoZXJlIGFyZSBzdGVwIGZ1bmN0aW9ucyBmb3IgYSB2YXJpZXR5IG9mIHB1cnBvc2VzOjwvdT4KCjEuIFsqKkltcHV0YXRpb24qKl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSW1wdXRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gLS0gZmlsbGluZyBpbiBtaXNzaW5nIHZhbHVlcyBiYXNlZCBvbiB0aGUgZXhpc3RpbmcgZGF0YSAKMi4gWyoqVHJhbnNmb3JtYXRpb24qKl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRGF0YV90cmFuc2Zvcm1hdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gLS0gY2hhbmdpbmcgYWxsIHZhbHVlcyBvZiBhIHZhcmlhYmxlIGluIHRoZSBzYW1lIHdheSwgdHlwaWNhbGx5IHRvIG1ha2UgaXQgbW9yZSBub3JtYWwgb3IgZWFzaWVyIHRvIGludGVycHJldAozLiBbKipEaXNjcmV0aXphdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EaXNjcmV0aXphdGlvbl9vZl9jb250aW51b3VzX2ZlYXR1cmVzKXt0YXJnZXQ9Il9ibGFuayJ9IC0tIGNvbnZlcnRpbmcgY29udGludW91cyB2YWx1ZXMgaW50byBkaXNjcmV0ZSBvciBub21pbmFsIHZhbHVlcyAtIGJpbm5pbmcgZm9yIGV4YW1wbGUgdG8gcmVkdWNlIHRoZSBudW1iZXIgb2YgcG9zc2libGUgbGV2ZWxzIChIb3dldmVyIHRoaXMgaXMgZ2VuZXJhbGx5IG5vdCBhZHZpc2FibGUhKQo0LiBbKipFbmNvZGluZyAvIENyZWF0aW5nIER1bW15IFZhcmlhYmxlcyoqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EdW1teV92YXJpYWJsZV8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gLS0gY3JlYXRpbmcgYSBudW1lcmljIGNvZGUgZm9yIGNhdGVnb3JpY2FsIHZhcmlhYmxlcwooWyoqTW9yZSBvbiBEdW1teSBWYXJpYWJsZXMgYW5kIG9uZSBob3QgZW5jb2RpbmcqKl0oaHR0cHM6Ly9tZWRpdW0uY29tL3AvYjU4NDBiZTNjNDFhL3Jlc3BvbnNlcy9zaG93KXt0YXJnZXQ9Il9ibGFuayJ9KQo1LiBbKipEYXRhIHR5cGUgY29udmVyc2lvbnMqKl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2hhYmxhci92aWduZXR0ZXMvY29udmVydC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAtLSB3aGljaCBtZWFucyBjaGFuZ2luZyBmcm9tIGludGVnZXIgdG8gZmFjdG9yIG9yIG51bWVyaWMgdG8gZGF0ZSBldGMuCjYuIFsqKkludGVyYWN0aW9uKipdKGh0dHBzOi8vc3RhdGlzdGljc2J5amltLmNvbS9yZWdyZXNzaW9uL2ludGVyYWN0aW9uLWVmZmVjdHMvKXt0YXJnZXQ9Il9ibGFuayJ9ICB0ZXJtIGFkZGl0aW9uIHRvIHRoZSBtb2RlbCAtLSB3aGljaCBtZWFucyB0aGF0IHdlIHdvdWxkIGJlIG1vZGVsaW5nIGZvciBwcmVkaWN0b3JzIHRoYXQgd291bGQgaW5mbHVlbmNlIHRoZSBjYXBhY2l0eSBvZiBlYWNoIG90aGVyIHRvIHByZWRpY3QgdGhlIG91dGNvbWUKNy4gWyoqTm9ybWFsaXphdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Ob3JtYWxpemF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAtLSBjZW50ZXJpbmcgYW5kIHNjYWxpbmcgdGhlIGRhdGEgdG8gYSBzaW1pbGFyIHJhbmdlIG9mIHZhbHVlcwo4LiBbKipEaW1lbnNpb25hbGl0eSBSZWR1Y3Rpb24vIFNpZ25hbCBFeHRyYWN0aW9uKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0RpbWVuc2lvbmFsaXR5X3JlZHVjdGlvbil7dGFyZ2V0PSJfYmxhbmsifSAtLSByZWR1Y2luZyB0aGUgc3BhY2Ugb2YgZmVhdHVyZXMgb3IgcHJlZGljdG9ycyB0byBhIHNtYWxsZXIgc2V0IG9mIHZhcmlhYmxlcyB0aGF0IGNhcHR1cmUgdGhlIHZhcmlhdGlvbiBvciBzaWduYWwgaW4gdGhlIG9yaWdpbmFsIHZhcmlhYmxlcyAoZXguIFByaW5jaXBhbCBDb21wb25lbnQgQW5hbHlzaXMgYW5kIEluZGVwZW5kZW50IENvbXBvbmVudCBBbmFseXNpcykKOS4gKipGaWx0ZXJpbmcqKiAtLSBmaWx0ZXJpbmcgb3B0aW9ucyBmb3IgcmVtb3ZpbmcgdmFyaWFibGVzIChleC4gcmVtb3ZlIHZhcmlhYmxlcyB0aGF0IGFyZSBoaWdobHkgY29ycmVsYXRlZCB0byBvdGhlcnMgb3IgcmVtb3ZlIHZhcmlhYmxlcyB3aXRoIHZlcnkgbGl0dGxlIHZhcmlhbmNlIGFuZCB0aGVyZWZvcmUgbGlrZWx5IGxpdHRsZSBwcmVkaWN0aXZlIGNhcGFjaXR5KQoxMC4gWyoqUm93IG9wZXJhdGlvbnMqKl0oaHR0cHM6Ly90YXJ0YXJ1cy5vcmcvZ2FyZXRoL21hdGhzL0xpbmVhcl9BbGdlYnJhL3Jvd19vcGVyYXRpb25zLnBkZil7dGFyZ2V0PSJfYmxhbmsifSAtLSBwZXJmb3JtaW5nIGZ1bmN0aW9ucyBvbiB0aGUgdmFsdWVzIHdpdGhpbiB0aGUgcm93cyAgKGV4LiByZWFycmFuZ2luZywgZmlsdGVyaW5nLCBpbXB1dGluZykKMTEuICoqQ2hlY2tpbmcgZnVuY3Rpb25zKiogLS0gU2FuaXR5IGNoZWNrcyB0byBsb29rIGZvciBtaXNzaW5nIHZhbHVlcywgdG8gbG9vayBhdCB0aGUgdmFyaWFibGUgY2xhc3NlcyBldGMuCgpBbGwgb2YgdGhlIHN0ZXAgZnVuY3Rpb25zIGxvb2sgbGlrZSBgc3RlcF8qKClgIHdpdGggdGhlIGAqYCByZXBsYWNlZCB3aXRoIGEgbmFtZSwgZXhjZXB0IGZvciB0aGUgY2hlY2sgZnVuY3Rpb25zIHdoaWNoIGxvb2sgbGlrZSBgY2hlY2tfKigpYC4KClRoZXJlIGFyZSBzZXZlcmFsIHdheXMgdG8gc2VsZWN0IHdoYXQgdmFyaWFibGVzIHRvIGFwcGx5IHN0ZXBzIHRvOiAgCgoxLiBVc2luZyBgdGlkeXNlbGVjdGAgbWV0aG9kczogYGNvbnRhaW5zKClgLCBgbWF0Y2hlcygpYCwgYHN0YXJ0c193aXRoKClgLCBgZW5kc193aXRoKClgLCBgZXZlcnl0aGluZygpYCwgYG51bV9yYW5nZSgpYCAgCjIuIFVzaW5nIHRoZSB0eXBlOiBgYWxsX25vbWluYWwoKWAsIGBhbGxfbnVtZXJpYygpYCAsIGBoYXNfdHlwZSgpYCAKMy4gVXNpbmcgdGhlIHJvbGU6IGBhbGxfcHJlZGljdG9ycygpYCwgYGFsbF9vdXRjb21lcygpYCwgYGhhc19yb2xlKClgCjQuIFVzaW5nIHRoZSBuYW1lIC0gdXNlIHRoZSBhY3R1YWwgbmFtZSBvZiB0aGUgdmFyaWFibGUvdmFyaWFibGVzIG9mIGludGVyZXN0ICAKCkxldCdzIHRyeSBhZGRpbmcgc29tZSBzdGVwcyB0byBvdXIgcmVjaXBlLgoKCldlIG1pZ2h0IHdhbnQgdG8gcG90ZW50aWFsbHkgW29uZSBob3QgZW5jb2RlXShodHRwczovL21hY2hpbmVsZWFybmluZ21hc3RlcnkuY29tL3doeS1vbmUtaG90LWVuY29kZS1kYXRhLWluLW1hY2hpbmUtbGVhcm5pbmcvKXt0YXJnZXQ9Il9ibGFuayJ9IHNvbWUgb2Ygb3VyIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBzbyB0aGF0IHRoZXkgY2FuIGJlIHVzZWQgd2l0aCBjZXJ0YWluIGFsZ29yaXRobXMuIAoKV2UgY2FuIGRvIHRoaXMgd2l0aCB0aGUgYHN0ZXBfZHVtbXkoKWAgZnVuY3Rpb24gYW5kIHRoZSBgb25lX2hvdCA9IFRSVUVgIGFyZ3VtZW50LiAKT25lIGhvdCBlbmNvZGluZyBtZWFucyB0aGF0IHdlIGRvIG5vdCBzaW1wbHkgZW5jb2RlIG91ciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgbnVtZXJpY2FsbHksIGFzIG91ciBudW1lcmljIGFzc2lnbm1lbnRzIGNhbiBiZSBpbnRlcnByZXRlZCBieSBhbGdvcml0aG1zIGFzIGhhdmluZyBhIHBhcnRpY3VsYXIgcmFuayBvciBvcmRlci4gCkluc3RlYWQsIGJpbmFyeSB2YXJpYWJsZXMgbWFkZSBvZiAxcyBhbmQgMHMgYXJlIHVzZWQgdG8gYXJiaXRyYXJpbHkgYXNzaWduIGEgbnVtZXJpYyB2YWx1ZSB0aGF0IGhhcyBubyBhcHBhcmVudCBvcmRlci4KCmBgYHtyfQpzaW1wbGVfcmVjICU+JQogIHN0ZXBfZHVtbXkoc3RhdGUsIGNvdW50eSwgY2l0eSwgemN0YSwgb25lX2hvdCA9IFRSVUUpCmBgYAoKT3VyIGBmaXBzYCB2YXJpYWJsZSBpbmNsdWRlcyBhIG51bWVyaWMgY29kZSBmb3Igc3RhdGUgYW5kIGNvdW50eSAtIGFuZCB0aGVyZWZvcmUgaXMgZXNzZW50aWFsbHkgYSBwcm94eSBmb3IgY291bnR5LgpTaW5jZSB3ZSBhbHJlYWR5IGhhdmUgY291bnR5LCB3ZSB3aWxsIGp1c3QgdXNlIGl0IGFuZCBrZWVwIHRoZSBgZmlwc2AgSUQgYXMgYW5vdGhlciBJRCB2YXJpYWJsZS4KCldlIGNhbiByZW1vdmUgdGhlIGBmaXBzYCB2YXJpYWJsZSBmcm9tIHRoZSBwcmVkaWN0b3JzIHVzaW5nIGB1cGRhdGVfcm9sZSgpYCB0byBtYWtlIHN1cmUgdGhhdCB0aGUgcm9sZSBpcyBubyBsb25nZXIgYCJwcmVkaWN0b3IiYC4gCldlIGNhbiBtYWtlIHRoZSByb2xlIGFueXRoaW5nIHdlIHdhbnQgYWN0dWFsbHksIHNvIHdlIHdpbGwga2VlcCBpdCBzb21ldGhpbmcgaWRlbnRpZmlhYmxlLgoKYGBge3J9CnNpbXBsZV9yZWMgJT4lCiAgdXBkYXRlX3JvbGUoImZpcHMiLCBuZXdfcm9sZSA9ICJjb3VudHkgaWQiKQpgYGAKCldlIG1pZ2h0IGFsc28gd2FudCB0byByZW1vdmUgdmFyaWFibGVzIHRoYXQgYXBwZWFyIHRvIGJlIHJlZHVuZGFudCBhbmQgYXJlIGhpZ2hseSBjb3JyZWxhdGVkIHdpdGggb3RoZXJzLCBhcyB3ZSBrbm93IGZyb20gb3VyIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgdGhhdCBtYW55IG9mIG91ciB2YXJpYWJsZXMgYXJlIGNvcnJlbGF0ZWQgd2l0aCBvbmUgYW5vdGhlci4gCldlIGNhbiBkbyB0aGlzIHVzaW5nIHRoZSBgc3RlcF9jb3JyKClgIGZ1bmN0aW9uLgoKV2UgZG9uJ3Qgd2FudCB0byByZW1vdmUgc29tZSBvZiBvdXIgdmFyaWFibGVzLCBsaWtlIHRoZSBgQ01BUWAgYW5kIGBhb2RgIHZhcmlhYmxlcywgd2UgY2FuIHNwZWNpZnkgdGhpcyB1c2luZyB0aGUgYC1gIHNpZ24gYmVmb3JlIHRoZSBuYW1lcyBvZiB0aGVzZSB2YXJpYWJsZXMgbGlrZSBzbzoKCmBgYHtyfQpzaW1wbGVfcmVjICU+JQogIHN0ZXBfY29ycihhbGxfcHJlZGljdG9ycygpLCAtIENNQVEsIC0gYW9kKQpgYGAKCgpJdCBpcyBhbHNvIGEgZ29vZCBpZGVhIHRvIHJlbW92ZSB2YXJpYWJsZXMgd2l0aCBuZWFyLXplcm8gdmFyaWFuY2UsIHdoaWNoIGNhbiBiZSBkb25lIHdpdGggdGhlIGBzdGVwX256digpYCBmdW5jdGlvbi4gCgpWYXJpYWJsZXMgaGF2ZSBsb3cgdmFyaWFuY2UgaWYgYWxsIHRoZSB2YWx1ZXMgYXJlIHZlcnkgc2ltaWxhciwgdGhlIHZhbHVlcyBhcmUgdmVyeSBzcGFyc2UsIG9yIGlmIHRoZXkgYXJlIGhpZ2hseSBpbWJhbGFuY2VkLiBBZ2FpbiB3ZSBkb24ndCB3YW50IHRvIHJlbW92ZSBvdXIgYENNQVFgIGFuZCBgYW9kYCB2YXJpYWJsZXMuCgpgYGB7cn0Kc2ltcGxlX3JlYyAlPiUKICBzdGVwX256dihhbGxfcHJlZGljdG9ycygpLCAtIENNQVEsIC0gYW9kKQpgYGAKCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIGxlYXJuIGFib3V0IGV4YW1wbGVzIHdoZXJlIHlvdSBtaWdodCBoYXZlIG5lYXItemVybyB2YXJpYW5jZSB2YXJpYWJsZXM8L3N1bW1hcnk+CgoxKSAqKlNpbWlsYXIgVmFsdWVzKiogLSBJZiB0aGUgcG9wdWxhdGlvbiBkZW5zaXR5IHdhcyBuZWFybHkgdGhlIHNhbWUgZm9yIGV2ZXJ5IHpjdGEgdGhhdCBjb250YWluZWQgYSBtb25pdG9yLCB0aGVuIGtub3dpbmcgdGhlIHBvcHVsYXRpb24gZGVuc2l0eSBuZWFyIG91ciBtb25pdG9yIHdvdWxkIGNvbnRyaWJ1dGUgbGl0dGxlIHRvIG91ciBtb2RlbCBpbiBhc3Npc3RpbmcgdXMgdG8gcHJlZGljdCBtb25pdG9yIGFpciBwb2xsdXRpb24gdmFsdWVzLiAKMikgKipTcGFyc2UgRGF0YSoqIC0gSWYgYWxsIG9mIHRoZSBtb25pdG9ycyB3ZXJlIGluIGxvY2F0aW9ucyB3aGVyZSB0aGUgcG9wdWxhdGlvbnMgZGlkIG5vdCBhdHRlbmQgZ3JhZHVhdGUgc2Nob29sLCB0aGVuIHRoZXNlIHZhbHVlcyB3b3VsZCBtb3N0bHkgYmUgemVybywgYWdhaW4gdGhpcyB3b3VsZCBkbyB2ZXJ5IGxpdHRsZSB0byBoZWxwIHVzIGRpc3Rpbmd1aXNoIG91ciBhaXIgcG9sbHV0aW9uIG1vbml0b3JzLldoZW4gbWFueSBvZiB0aGUgdmFsdWVzIGFyZSB6ZXJvIHRoaXMgaXMgYWxzbyBjYWxsZWQgc3BhcnNlIGRhdGEuICAKMykgKipJbWJhbGFuY2VkIERhdGEqKiBJZiBuZWFybHkgYWxsIG9mIHRoZSBtb25pdG9ycyB3ZXJlIGxvY2F0ZWQgaW4gb25lIHBhcnRpY3VsYXIgc3RhdGUsIGFuZCBhbGwgdGhlIG90aGVycyBvbmx5IGhhZCBvbmUgbW9uaXRvciBlYWNoLCB0aGVuIHRoZSByZWFsIHByZWRpY3RpdmUgdmFsdWUgd291bGQgc2ltcGx5IGJlIGluIGtub3dpbmcgaWYgYSBtb25pdG9yIGlzIGxvY2F0ZWQgaW4gdGhhdCBwYXJ0aWN1bGFyIHN0YXRlIG9yIG5vdC4gSW4gdGhpcyBjYXNlIHdlIGRvbid0IHdhbnQgdG8gcmVtb3ZlIG91ciB2YXJpYWJsZSwgd2UganVzdCB3YW50IHRvIHNpbXBsaWZ5IGl0LgoKU2VlIHRoaXMgW2Jsb2cgcG9zdF0oaHR0cHM6Ly93d3cuci1ibG9nZ2Vycy5jb20vbmVhci16ZXJvLXZhcmlhbmNlLXByZWRpY3RvcnMtc2hvdWxkLXdlLXJlbW92ZS10aGVtLyl7dGFyZ2V0PSJfYmxhbmsifSBhYm91dCB3aHkgcmVtb3ZpbmcgbmVhci16ZXJvIHZhcmlhbmNlIHZhcmlhYmxlcyBpc24ndCBhbHdheXMgYSBnb29kIGlkZWEgaWYgd2UgdGhpbmsgdGhhdCBhIHZhcmlhYmxlIG1pZ2h0IGJlIGVzcGVjaWFsbHkgaW5mb3JtYXRpdmUuCgo8L2RldGFpbHM+CgpMZXQncyBwdXQgYWxsIHRoaXMgdG9nZXRoZXIgbm93LiAKCioqUmVtZW1iZXI6IGl0IGlzIGltcG9ydGFudCB0byBhZGQgdGhlIHN0ZXBzIHRvIHRoZSByZWNpcGUgaW4gYW4gb3JkZXIgdGhhdCBtYWtlcyBzZW5zZSBqdXN0IGxpa2Ugd2l0aCBhIGNvb2tpbmcgcmVjaXBlLioqCgpGaXJzdCwgd2UgYXJlIGdvaW5nIHRvIGNyZWF0ZSBudW1lcmljIHZhbHVlcyBmb3Igb3VyIGNhdGVnb3JpY2FsIHZhcmlhYmxlcywgdGhlbiB3ZSB3aWxsIGxvb2sgYXQgY29ycmVsYXRpb24gYW5kIG5lYXItemVybyB2YXJpYW5jZS4gCkFnYWluLCB3ZSBkbyBub3Qgd2FudCB0byByZW1vdmUgdGhlIGBDTUFRYCBhbmQgYGFvZGAgdmFyaWFibGVzLCBzbyB3ZSBjYW4gbWFrZSBzdXJlIHRoZXkgYXJlIGtlcHQgaW4gdGhlIG1vZGVsIGJ5IGV4Y2x1ZGluZyB0aGVtIGZyb20gdGhvc2Ugc3RlcHMuIApJZiB3ZSBzcGVjaWZpY2FsbHkgd2FudGVkIHRvIHJlbW92ZSBhIHByZWRpY3RvciB3ZSBjb3VsZCB1c2UgYHN0ZXBfcm0oKWAuCgpgYGB7cn0Kc2ltcGxlX3JlYyAlPD4lCiAgdXBkYXRlX3JvbGUoImZpcHMiLCBuZXdfcm9sZSA9ICJjb3VudHkgaWQiKSAlPiUKICBzdGVwX2R1bW15KHN0YXRlLCBjb3VudHksIGNpdHksIHpjdGEsIG9uZV9ob3QgPSBUUlVFKSAlPiUKICBzdGVwX2NvcnIoYWxsX3ByZWRpY3RvcnMoKSwgLSBDTUFRLCAtIGFvZCklPiUKICBzdGVwX256dihhbGxfcHJlZGljdG9ycygpLCAtIENNQVEsIC0gYW9kKQogIApzaW1wbGVfcmVjCmBgYAoKCgojIyBSdW5uaW5nIHRoZSBwcmUtcHJvY2Vzc2luZwoKIyMjIFN0ZXAgMTogVXBkYXRlIHRoZSByZWNpcGUgd2l0aCB0cmFpbmluZyBkYXRhIHVzaW5nIGBwcmVwKClgCgpUaGUgbmV4dCBtYWpvciBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UgaXMgYHByZXAoKWAuClRoaXMgZnVuY3Rpb24gdXBkYXRlcyB0aGUgcmVjaXBlIG9iamVjdCBiYXNlZCBvbiB0aGUgdHJhaW5pbmcgZGF0YS4gCkl0IGVzdGltYXRlcyBwYXJhbWV0ZXJzIChlc3RpbWF0aW5nIHRoZSByZXF1aXJlZCBxdWFudGl0aWVzIGFuZCBzdGF0aXN0aWNzIHJlcXVpcmVkIGJ5IHRoZSBzdGVwcyBmb3IgdGhlIHZhcmlhYmxlcykgZm9yIHByZS1wcm9jZXNzaW5nIGFuZCB1cGRhdGVzIHRoZSB2YXJpYWJsZXMgcm9sZXMsIGFzIHNvbWUgb2YgdGhlIHByZWRpY3RvcnMgbWF5IGJlIHJlbW92ZWQsIHRoaXMgYWxsb3dzIHRoZSByZWNpcGUgdG8gYmUgcmVhZHkgdG8gdXNlIG9uIG90aGVyIGRhdGEgc2V0cy4gCkl0ICoqZG9lcyBub3QgbmVjZXNzYXJpbHkgYWN0dWFsbHkgZXhlY3V0ZSB0aGUgcHJlLXByb2Nlc3NpbmcgaXRzZWxmKiosIGhvd2V2ZXIgd2Ugd2lsbCBzcGVjaWZ5IGluIGFyZ3VtZW50IGZvciBpdCB0byBkbyB0aGlzIHNvIHRoYXQgd2UgY2FuIHRha2UgYSBsb29rIGF0IHRoZSBwcmUtcHJvY2Vzc2VkIGRhdGEuCgoKVGhlcmUgYXJlIHNvbWUgaW1wb3J0YW50IGFyZ3VtZW50cyB0byBrbm93IGFib3V0OgoKMS4gYHRyYWluaW5nYCAtIHlvdSBtdXN0IHN1cHBseSBhIHRyYWluaW5nIGRhdGEgc2V0IHRvIGVzdGltYXRlIHBhcmFtZXRlcnMgZm9yIHByZS1wcm9jZXNzaW5nIG9wZXJhdGlvbnMgKHJlY2lwZSBzdGVwcykgLSB0aGlzIG1heSBhbHJlYWR5IGJlIGluY2x1ZGVkIGluIHlvdXIgcmVjaXBlIC0gYXMgaXMgdGhlIGNhc2UgZm9yIHVzCjIuIGBmcmVzaGAgLSBpZiBgZnJlc2g9VFJVRWAsIC0gd2lsbCByZXRyYWluIGFuZCBlc3RpbWF0ZSBwYXJhbWV0ZXJzIGZvciBhbnkgcHJldmlvdXMgc3RlcHMgdGhhdCB3ZXJlIGFscmVhZHkgcHJlcHBlZCBpZiB5b3UgYWRkIG1vcmUgc3RlcHMgdG8gdGhlIHJlY2lwZQozLiBgdmVyYm9zZWAgLSBpZiBgdmVyYm9zZT1UUlVFYCwgc2hvd3MgdGhlIHByb2dyZXNzIGFzIHRoZSBzdGVwcyBhcmUgZXZhbHVhdGVkIGFuZCB0aGUgc2l6ZSBvZiB0aGUgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBzZXQKNC4gYHJldGFpbmAgLSBpZiBgcmV0YWluPVRSVUVgLCB0aGVuIHRoZSBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIHNldCB3aWxsIGJlIHNhdmVkIHdpdGhpbiB0aGUgcmVjaXBlIChhcyB0ZW1wbGF0ZSkuIFRoaXMgaXMgZ29vZCBpZiB5b3UgYXJlIGxpa2VseSB0byBhZGQgbW9yZSBzdGVwcyBhbmQgZG8gbm90IHdhbnQgdG8gcmVydW4gdGhlIGBwcmVwKClgIG9uIHRoZSBwcmV2aW91cyBzdGVwcy4gSG93ZXZlciB0aGlzIGNhbiBtYWtlIHRoZSByZWNpcGUgc2l6ZSBsYXJnZS4gVGhpcyBpcyBuZWNlc3NhcnkgaWYgeW91IHdhbnQgdG8gYWN0dWFsbHkgbG9vayBhdCB0aGUgcHJlLXByb2Nlc3NlZCBkYXRhLgoKTGV0J3MgdHJ5IG91dCB0aGUgYHByZXAoKWAgZnVuY3Rpb246IAoKYGBge3J9CnByZXBwZWRfcmVjIDwtIHByZXAoc2ltcGxlX3JlYywgdmVyYm9zZSA9IFRSVUUsIHJldGFpbiA9IFRSVUUgKQpuYW1lcyhwcmVwcGVkX3JlYykKYGBgCgpUaGVyZSBhcmUgYWxzbyBsb3RzIG9mIHVzZWZ1bCB0aGluZ3MgdG8gY2hlY2tvdXQgaW4gdGhlIG91dHB1dCBvZiBgcHJlcCgpYC4KWW91IGNhbiBzZWU6CgoxLiB0aGUgYHN0ZXBzYCB0aGF0IHdlcmUgcnVuICAKMi4gdGhlIG9yaWdpbmFsIHZhcmlhYmxlIGluZm8gKGB2YXJfaW5mb2ApICAKMy4gdGhlIHVwZGF0ZWQgdmFyaWFibGUgaW5mbyBhZnRlciBwcmUtcHJvY2Vzc2luZyAoYHRlcm1faW5mb2ApCjQuIHRoZSBuZXcgYGxldmVsc2Agb2YgdGhlIHZhcmlhYmxlcyAKNS4gdGhlIG9yaWdpbmFsIGxldmVscyBvZiB0aGUgdmFyaWFibGVzIChgb3JpZ19sdmxzYCkKNi4gaW5mbyBhYm91dCB0aGUgdHJhaW5pbmcgZGF0YSBzZXQgc2l6ZSBhbmQgY29tcGxldGVuZXNzIChgdHJfaW5mb2ApCgoqKk5vdGUqKjogWW91IG1heSBzZWUgdGhlIGBwcmVwLnJlY2lwZSgpYCBmdW5jdGlvbiBpbiBtYXRlcmlhbCB0aGF0IHlvdSByZWFkIGFib3V0IHRoZSBgcmVjaXBlc2AgcGFja2FnZS4gVGhpcyBpcyByZWZlcnJpbmcgdG8gdGhlIGBwcmVwKClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVjaXBlc2AgcGFja2FnZS4KCgojIyMgU3RlcCAyOiBFeHRyYWN0IHByZS1wcm9jZXNzZWQgdHJhaW5pbmcgZGF0YSB1c2luZyBganVpY2UoKWAKClNpbmNlIHdlIHJldGFpbmVkIG91ciBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgKGkuZS4gYHByZXAocmV0YWluPVRSVUUpYCksIHdlIGNhbiB0YWtlIGEgbG9vayBhdCBpdCBsaWtlIGJ5IHVzaW5nIHRoZSBganVpY2UoKWAgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlIGxpa2UgdGhpczoKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjQwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwidHJhaW5pbmdfcHJlcHJvY2Vzc2luZ19yZWNpcGVzMy5wbmciKSkKYGBgCgpMZXQncyBqdWljZSEgCgoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cn0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpqdWljZWRfdHJhaW4gPC0ganVpY2UocHJlcHBlZF9yZWMpCmdsaW1wc2UoanVpY2VkX3RyYWluKQpgYGAKIyMjIwoKCkZvciBlYXN5IGNvbXBhcmlzb24gc2FrZSAtIGhlcmUgaXMgb3VyIG9yaWdpbmFsIGRhdGE6CgojIyMjIHsuc2Nyb2xsYWJsZSB9CgpgYGB7cn0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpnbGltcHNlKHBtKQpgYGAKIyMjIwoKTm90aWNlIGhvdyB3ZSBvbmx5IGhhdmUgMzYgdmFyaWFibGVzIG5vdyBpbnN0ZWFkIG9mIDUwISAKVHdvIG9mIHRoZXNlIGFyZSBvdXIgSUQgdmFyaWFibGVzIChgZmlwc2AgYW5kIHRoZSBhY3R1YWwgbW9uaXRvciBJRCAoYGlkYCkpIGFuZCBvbmUgaXMgb3VyIG91dGNvbWUgKGB2YWx1ZWApLiAKVGh1cyB3ZSBvbmx5IGhhdmUgMzMgcHJlZGljdG9ycyBub3cuIApXZSBjYW4gYWxzbyBzZWUgdGhhdCB3ZSBubyBsb25nZXIgaGF2ZSBhbnkgY2F0ZWdvcmljYWwgdmFyaWFibGVzLiAKVmFyaWFibGVzIGxpa2UgYHN0YXRlYCBhcmUgZ29uZSBhbmQgb25seSBgc3RhdGVfQ2FsaWZvcm5pYWAgcmVtYWlucyBhcyBpdCB3YXMgdGhlIG9ubHkgc3RhdGUgaWRlbnRpdHkgdG8gaGF2ZSBub256ZXJvIHZhcmlhbmNlLgpXZSBjYW4gYWxzbyBzZWUgdGhhdCB0aGVyZSB3ZXJlIG1vcmUgbW9uaXRvcnMgbGlzdGVkIGFzIGAiTm90IGluIGEgY2l0eSJgIHRoYW4gYW55IGNpdHkuIAoKV2UgY2FuIHNlZSB0aGF0IENhbGlmb3JuaWEgaGFkIHRoZSBsYXJnZXN0IG51bWJlciBvZiBtb25pdG9ycyBjb21wYXJlZCB0byB0aGUgb3RoZXIgc3RhdGVzLgoKYGBge3IsIGV2YWwgPSBGQUxTRX0KcG0gJT4lIGNvdW50KHN0YXRlKSAKYGBgCgoKU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dDoKCiMjIyMgey5zY3JvbGxhYmxlIH0KCmBgYHtyLCBlY2hvID0gRkFMU0V9CnBtICU+JSBjb3VudChzdGF0ZSkgICU+JQogIHByaW50KG4gPSAxZTMpCmBgYAoKIyMjIwoKYGBge3IsIGV2YWwgPSBGQUxTRX0KcG0gJT4lIGNvdW50KGNpdHkpCmBgYAoKU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dDoKCiMjIyMgey5zY3JvbGxhYmxlIH0KCmBgYHtyLCBlY2hvPUZBTFNFfQpwbSAlPiUgY291bnQoY2l0eSkgJT4lCiAgcHJpbnQobiA9IDFlMykKYGBgCgojIyMjCgoqKk5vdGUqKjogUmVjYWxsIHRoYXQgeW91IG11c3Qgc3BlY2lmeSBgcmV0YWluID0gVFJVRWAgYXJndW1lbnQgb2YgdGhlIGBwcmVwKClgIGZ1bmN0aW9uIHRvIHVzZSBganVpY2UoKWAuCgojIyMgU3RlcCAzOiBFeHRyYWN0IHByZS1wcm9jZXNzZWQgdGVzdGluZyBkYXRhIHVzaW5nIGBiYWtlKClgCgpBY2NvcmRpbmcgdG8gdGhlIGB0aWR5bW9kZWxzYCBkb2N1bWVudGF0aW9uOgoKPiBgYmFrZSgpYCB0YWtlcyBhIHRyYWluZWQgcmVjaXBlIGFuZCBhcHBsaWVzIHRoZSBvcGVyYXRpb25zIHRvIGEgZGF0YSBzZXQgdG8gY3JlYXRlIGEgZGVzaWduIG1hdHJpeC4KIEZvciBleGFtcGxlOiBpdCBhcHBsaWVzIHRoZSBjZW50ZXJpbmcgdG8gbmV3IGRhdGEgc2V0cyB1c2luZyB0aGVzZSBtZWFucyB1c2VkIHRvIGNyZWF0ZSB0aGUgcmVjaXBlLgoKVGhlcmVmb3JlLCBpZiB5b3Ugd2FudGVkIHRvIGxvb2sgYXQgdGhlIHByZS1wcm9jZXNzZWQgdGVzdGluZyBkYXRhIHlvdSB3b3VsZCB1c2UgdGhlIGBiYWtlKClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVjaXBlc2AgcGFja2FnZS4KKFlvdSBnZW5lcmFsbHkgd2FudCB0byBsZWF2ZSB5b3VyIHRlc3RpbmcgZGF0YSBhbG9uZSwgYnV0IGl0IGlzIGdvb2QgdG8gbG9vayBmb3IgaXNzdWVzIGxpa2UgdGhlIGludHJvZHVjdGlvbiBvZiBOQSB2YWx1ZXMpLgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNDAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJ0ZXN0aW5nX3ByZXByb2Nlc3NpbmdfcmVjaXBlczQucG5nIikpCmBgYAoKTGV0J3MgYmFrZSEgCgojIyMjIHsuc2Nyb2xsYWJsZSB9CmBgYHtyLH0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpiYWtlZF90ZXN0X3BtIDwtIHJlY2lwZXM6OmJha2UocHJlcHBlZF9yZWMsIG5ld19kYXRhID0gdGVzdF9wbSkKZ2xpbXBzZShiYWtlZF90ZXN0X3BtKQpgYGAKIyMjIwoKCk5vdGljZSB0aGF0IG91ciBgY2l0eV9Ob3QuaW4uYS5jaXR5YCB2YXJpYWJsZSBzZWVtcyB0byBiZSBOQSB2YWx1ZXMuIApXaHkgbWlnaHQgdGhhdCBiZT8KCkFoISBQZXJoYXBzIGl0IGlzIGJlY2F1c2Ugc29tZSBvZiBvdXIgbGV2ZWxzIHdlcmUgbm90IHByZXZpb3VzbHkgc2VlbiBpbiB0aGUgdHJhaW5pbmcgc2V0IQoKTGV0J3MgdGFrZSBhIGxvb2sgdXNpbmcgdGhlIFtzZXQgb3BlcmF0aW9uc10oaHR0cHM6Ly93d3cucHJvYmFiaWxpdHljb3Vyc2UuY29tL2NoYXB0ZXIxLzFfMl8yX3NldF9vcGVyYXRpb25zLnBocCl7dGFyZ2V0PSJfYmxhbmsifSBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiAKV2UgY2FuIHRha2UgYSBsb29rIGF0IGNpdGllcyB0aGF0IHdlcmUgZGlmZmVyZW50IGJldHdlZW4gdGhlIHRlc3QgYW5kIHRyYWluaW5nIHNldC4KCmBgYHtyfQp0cmFpbmNpdGllcyA8LSB0cmFpbl9wbSAlPiUgZGlzdGluY3QoY2l0eSkKdGVzdGNpdGllcyA8LSB0ZXN0X3BtICU+JSBkaXN0aW5jdChjaXR5KQoKI2dldCB0aGUgbnVtYmVyIG9mIGNpdGllcyB0aGF0IHdlcmUgZGlmZmVyZW50CmRpbShkcGx5cjo6c2V0ZGlmZih0cmFpbmNpdGllcywgdGVzdGNpdGllcykpCgojZ2V0IHRoZSBudW1iZXIgb2YgY2l0aWVzIHRoYXQgb3ZlcmxhcHBlZApkaW0oZHBseXI6OmludGVyc2VjdCh0cmFpbmNpdGllcywgdGVzdGNpdGllcykpCmBgYAoKSW5kZWVkLCB0aGVyZSBhcmUgbG90cyBvZiBkaWZmZXJlbnQgY2l0aWVzIGluIG91ciB0ZXN0IGRhdGEgdGhhdCBhcmUgbm90IGluIG91ciB0cmFpbmluZyBkYXRhIQoKClNvLCBsZXQgZ28gYmFjayB0byBvdXIgYHBtYCBkYXRhIHNldCBhbmQgbW9kaWZ5IHRoZSBgY2l0eWAgdmFyaWFibGUgdG8ganVzdCBiZSB2YWx1ZXMgb2YgYGluIGEgY2l0eWAgb3IgYG5vdCBpbiBhIGNpdHlgIHVzaW5nIHRoZSBgY2FzZV93aGVuKClgIGZ1bmN0aW9uIG9mIGBkcGx5cmAuClRoaXMgZnVuY3Rpb24gYWxsb3dzIHlvdSB0byB2ZWN0b3JpemUgbXVsdGlwbGUgYGlmX2Vsc2UoKWAgc3RhdGVtZW50cy4KCmBgYHtyfQpwbSAlPiUKICBtdXRhdGUoY2l0eSA9IGNhc2Vfd2hlbihjaXR5ID09ICJOb3QgaW4gYSBjaXR5IiB+ICJOb3QgaW4gYSBjaXR5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBjaXR5ICE9ICJOb3QgaW4gYSBjaXR5IiB+ICJJbiBhIGNpdHkiKSkKYGBgCgpBbHRlcm5hdGl2ZWx5IHlvdSBjb3VsZCBjcmVhdGUgYSBbY3VzdG9tIHN0ZXAgZnVuY3Rpb25dKGh0dHBzOi8vcmVjaXBlcy50aWR5bW9kZWxzLm9yZy9hcnRpY2xlcy9DdXN0b21fU3RlcHMuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSB0byBkbyB0aGlzIGFuZCBhZGQgdGhpcyB0byB5b3VyIHJlY2lwZSwgYnV0IHRoYXQgaXMgYmV5b25kIHRoZSBzY29wZSBvZiB0aGlzIGNhc2Ugc3R1ZHkuIAoKV2Ugd2lsbCBuZWVkIHRvIHJlcGVhdCBhbGwgdGhlIHN0ZXBzIChzcGxpdHRpbmcgdGhlIGRhdGEsIHByZS1wcm9jZXNzaW5nLCBldGMpIGFzIHRoZSBsZXZlbHMgb2Ygb3VyIHZhcmlhYmxlcyBoYXZlIG5vdyBjaGFuZ2VkLiAKCldoaWxlIHdlIGFyZSBkb2luZyB0aGlzLCB3ZSBtaWdodCBhbHNvIGhhdmUgdGhpcyBpc3N1ZSBmb3IgYGNvdW50eWAuIAoKVGhlIGBjb3VudHlgIHZhcmlhYmxlcyBhcHBlYXJzIHRvIGdldCBkcm9wcGVkIGR1ZSB0byBlaXRoZXIgY29ycmVsYXRpb24gb3IgbmVhciB6ZXJvIHZhcmlhbmNlLiAKCkl0IGlzIGxpa2VseSBkdWUgdG8gbmVhciB6ZXJvIHZhcmlhbmNlIGJlY2F1c2UgdGhpcyBpcyB0aGUgbW9yZSBncmFudWxhciBvZiB0aGVzZSBnZW9ncmFwaGljIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhbmQgbGlrZWx5IHNwYXJzZS4KCmBgYHtyfQpwbSAlPD4lCiAgbXV0YXRlKGNpdHkgPSBjYXNlX3doZW4oY2l0eSA9PSAiTm90IGluIGEgY2l0eSIgfiAiTm90IGluIGEgY2l0eSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2l0eSAhPSAiTm90IGluIGEgY2l0eSIgfiAiSW4gYSBjaXR5IikpCgpzZXQuc2VlZCgxMjM0KSAjIHNhbWUgc2VlZCBhcyBiZWZvcmUKcG1fc3BsaXQgPC1yc2FtcGxlOjppbml0aWFsX3NwbGl0KGRhdGEgPSBwbSwgcHJvcCA9IDIvMykKcG1fc3BsaXQKIHRyYWluX3BtIDwtcnNhbXBsZTo6dHJhaW5pbmcocG1fc3BsaXQpCiB0ZXN0X3BtIDwtcnNhbXBsZTo6dGVzdGluZyhwbV9zcGxpdCkKYGBgCgoKIyMjIyB7LnJlY2FsbF9jb2RlX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gUXVlc3Rpb24gT3Bwb3J0dW5pdHkgPC91PjwvYj4KClNlZSBpZiB5b3UgY2FuIGNvbWUgdXAgd2l0aCB0aGUgY29kZSBmb3IgdGhlIG5ldyByZWNpcGUuCgojIyMjCgoqKioKCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byByZXZlYWwgdGhlIGNvZGUgZm9yIHRoZSBuZXcgcmVjaXBlLiA8L3N1bW1hcnk+CgoKYGBge3J9Cm5vdmVsX3JlYyA8LXJlY2lwZSh0cmFpbl9wbSkgJT4lCiAgICB1cGRhdGVfcm9sZShldmVyeXRoaW5nKCksIG5ld19yb2xlID0gInByZWRpY3RvciIpICU+JQogICAgdXBkYXRlX3JvbGUodmFsdWUsIG5ld19yb2xlID0gIm91dGNvbWUiKSAlPiUKICAgIHVwZGF0ZV9yb2xlKGlkLCBuZXdfcm9sZSA9ICJpZCB2YXJpYWJsZSIpICU+JQogICAgdXBkYXRlX3JvbGUoImZpcHMiLCBuZXdfcm9sZSA9ICJjb3VudHkgaWQiKSAlPiUKICAgIHN0ZXBfZHVtbXkoc3RhdGUsIGNvdW50eSwgY2l0eSwgemN0YSwgb25lX2hvdCA9IFRSVUUpICU+JQogICAgc3RlcF9jb3JyKGFsbF9udW1lcmljKCkpICU+JQogICAgc3RlcF9uenYoYWxsX251bWVyaWMoKSkgCmBgYAo8L2RldGFpbHM+CioqKgoKYGBge3J9Cm5vdmVsX3JlYwpgYGAKCgoKTm93IGxldCdzIHJldHJhaW4gb3VyIHRyYWluaW5nIGRhdGEgYW5kIHRyeSBiYWtpbmcgb3VyIHRlc3QgZGF0YS4KCgoKIyMjIyB7LnJlY2FsbF9jb2RlX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gUXVlc3Rpb24gT3Bwb3J0dW5pdHkgPC91PjwvYj4KCkRvIHlvdSByZWNhbGwgaG93IHRvIHByZS1wcm9jZXNzIGFuZCBleHRyYWN0IHRoZSBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGE/CgojIyMjCgoqKioKCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byByZXZlYWwgdGhlIGFuc3dlci4gPC9zdW1tYXJ5PgoKYGBge3J9CnByZXBwZWRfcmVjIDwtIHByZXAobm92ZWxfcmVjLCB2ZXJib3NlID0gVFJVRSwgcmV0YWluID0gVFJVRSkKanVpY2VkX3RyYWluIDwtIGp1aWNlKHByZXBwZWRfcmVjKQpgYGAKPC9kZXRhaWxzPiAKKioqCgoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cn0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpnbGltcHNlKGp1aWNlZF90cmFpbikKYGBgCgojIyMjCgpBbmQgbm93LCBsZXQncyB0cnkgYmFraW5nIG91ciB0ZXN0IHNldCB0byBzZWUgaWYgd2Ugc3RpbGwgaGF2ZSBgTkFgIHZhbHVlcy4KCiMjIyMgey5zY3JvbGxhYmxlIH0KCmBgYHtyfQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhCmJha2VkX3Rlc3RfcG0gPC0gcmVjaXBlczo6YmFrZShwcmVwcGVkX3JlYywgbmV3X2RhdGEgPSB0ZXN0X3BtKQoKZ2xpbXBzZShiYWtlZF90ZXN0X3BtKQpgYGAKCiMjIyMKCkdyZWF0LCBub3cgd2Ugbm8gbG9uZ2VyIGhhdmUgYE5BYCB2YWx1ZXMhIDopCgoqKk5vdGUqKjogaWYgeW91IHVzZSB0aGUgc2tpcCBvcHRpb24gZm9yIHNvbWUgb2YgdGhlIHByZS1wcm9jZXNzaW5nIHN0ZXBzLCBiZSBjYXJlZnVsLiAKYGp1aWNlKClgIHdpbGwgc2hvdyBhbGwgb2YgdGhlIHJlc3VsdHMgaWdub3JpbmcgYHNraXAgPSBUUlVFYC4gCmBiYWtlKClgIHdpbGwgbm90IG5lY2Vzc2FyaWx5IGNvbmR1Y3QgdGhlc2Ugc3RlcHMgb24gdGhlIG5ldyBkYXRhLgoKCiMjIFNwZWNpZnlpbmcgdGhlIG1vZGVsCgpTbyBmYXIgd2UgaGF2ZSB1c2VkIHRoZSBwYWNrYWdlcyBgcnNhbXBsZWAgdG8gc3BsaXQgdGhlIGRhdGEgYW5kIGByZWNpcGVzYCB0byBhc3NpZ24gdmFyaWFibGUgdHlwZXMsIGFuZCB0byBzcGVjaWZ5IGFuZCBwcmVwIG91ciBwcmUtcHJvY2Vzc2luZyAoYXMgd2VsbCBhcyB0byBvcHRpb25hbGx5IGV4dHJhY3QgdGhlIHByZS1wcm9jZXNzZWQgZGF0YSkuCgpXZSB3aWxsIG5vdyB1c2UgdGhlIGBwYXJzbmlwYCBwYWNrYWdlICh3aGljaCBpcyBzaW1pbGFyIHRvIHRoZSBwcmV2aW91cyBgY2FyZXRgIHBhY2thZ2UgLSBhbmQgaGVuY2Ugd2h5IGl0IGlzIG5hbWVkIGFmdGVyIHRoZSB2ZWdldGFibGUpIHRvIHNwZWNpZnkgb3VyIG1vZGVsLgoKVGhlcmUgYXJlIGZvdXIgdGhpbmdzIHdlIG5lZWQgdG8gZGVmaW5lIGFib3V0IG91ciBtb2RlbDogIAoKMS4gVGhlICoqdHlwZSoqIG9mIG1vZGVsICh1c2luZyBzcGVjaWZpYyBmdW5jdGlvbnMgaW4gcGFyc25pcCBsaWtlIGByYW5kX2ZvcmVzdCgpYCwgYGxvZ2lzdGljX3JlZygpYCBldGMuKSAgCjIuIFRoZSBwYWNrYWdlIG9yICoqZW5naW5lKiogdGhhdCB3ZSB3aWxsIHVzZSB0byBpbXBsZW1lbnQgdGhlIHR5cGUgb2YgbW9kZWwgc2VsZWN0ZWQgKHVzaW5nIHRoZSBgc2V0X2VuZ2luZSgpYCBmdW5jdGlvbikgCjMuIFRoZSAqKm1vZGUqKiBvZiBsZWFybmluZyAtIGNsYXNzaWZpY2F0aW9uIG9yIHJlZ3Jlc3Npb24gKHVzaW5nIHRoZSBgc2V0X21vZGUoKWAgZnVuY3Rpb24pIAo0LiBBbnkgKiphcmd1bWVudHMqKiBuZWNlc3NhcnkgZm9yIHRoZSBtb2RlbC9wYWNrYWdlIHNlbGVjdGVkICh1c2luZyB0aGUgYHNldF9hcmdzKClgZnVuY3Rpb24gLSAgZm9yIGV4YW1wbGUgdGhlIGBtdHJ5ID1gIGFyZ3VtZW50IGZvciByYW5kb20gZm9yZXN0IHdoaWNoIGlzIHRoZSBudW1iZXIgb2YgdmFyaWFibGVzIHRvIGJlIHVzZWQgYXMgb3B0aW9ucyBmb3Igc3BsaXR0aW5nIGF0IGVhY2ggdHJlZSBub2RlKQoKTGV0J3Mgd2FsayB0aHJvdWdoIHRoZXNlIHN0ZXBzIG9uZSBieSBvbmUuIApGb3Igb3VyIGNhc2UsIHdlIGFyZSBnb2luZyB0byBzdGFydCBvdXIgYW5hbHlzaXMgd2l0aCBhIGxpbmVhciByZWdyZXNzaW9uIGJ1dCB3ZSB3aWxsIGRlbW9uc3RyYXRlIGhvdyB3ZSBjYW4gdHJ5IGRpZmZlcmVudCBtb2RlbHMuCgpUaGUgZmlyc3Qgc3RlcCBpcyB0byBkZWZpbmUgd2hhdCB0eXBlIG9mIG1vZGVsIHdlIHdvdWxkIGxpa2UgdG8gdXNlLiAKU2VlIFtoZXJlXShodHRwczovL3d3dy50aWR5bW9kZWxzLm9yZy9maW5kL3BhcnNuaXAvKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb2RlbGluZyBvcHRpb25zIGluIGBwYXJzbmlwYC4KCgpgYGB7cn0KUE1fbW9kZWwgPC0gcGFyc25pcDo6bGluZWFyX3JlZygpICMgUE0gd2FzIHVzZWQgaW4gdGhlIG5hbWUgZm9yIHBhcnRpY3VsYXRlIG1hdHRlcgpQTV9tb2RlbApgYGAKCk9LLiBTbyBmYXIsIGFsbCB3ZSBoYXZlIGRlZmluZWQgaXMgdGhhdCB3ZSB3YW50IHRvIHVzZSBhIGxpbmVhciByZWdyZXNzaW9uLi4uICAKTGV0J3MgdGVsbCBgcGFyc25pcGAgbW9yZSBhYm91dCB3aGF0IHdlIHdhbnQuCgpXZSB3b3VsZCBsaWtlIHRvIHVzZSB0aGUgW29yZGluYXJ5IGxlYXN0IHNxdWFyZXNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL09yZGluYXJ5X2xlYXN0X3NxdWFyZXMpIG1ldGhvZCB0byBmaXQgb3VyIGxpbmVhciByZWdyZXNzaW9uLiAKU28gd2Ugd2lsbCB0ZWxsIGBwYXJzbmlwYCB0aGF0IHdlIHdhbnQgdG8gdXNlIHRoZSBgbG1gIHBhY2thZ2UgdG8gaW1wbGVtZW50IG91ciBsaW5lYXIgcmVncmVzc2lvbiAodGhlcmUgYXJlIG1hbnkgb3B0aW9ucyBhY3R1YWxseSBzdWNoIGFzIFtgcnN0YW5gXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcnN0YW4vdmlnbmV0dGVzL3JzdGFuLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gIFtgZ2xtbmV0YF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2dsbW5ldC9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9LCBbYGtlcmFzYF0oaHR0cHM6Ly9rZXJhcy5yc3R1ZGlvLmNvbS8pe3RhcmdldD0iX2JsYW5rIn0sIGFuZCBbYHNwYXJrbHlyYF0oaHR0cHM6Ly90aGVyaW5zcGFyay5jb20vc3RhcnRpbmcuaHRtbCNzdGFydGluZy1zcGFya2x5ci1oZWxsby13b3JsZCl7dGFyZ2V0PSJfYmxhbmsifSkuIFNlZSBbaGVyZV0oaHR0cHM6Ly9wYXJzbmlwLnRpZHltb2RlbHMub3JnL3JlZmVyZW5jZS9saW5lYXJfcmVnLmh0bWwpIGZvciBhIGRlc2NyaXB0aW9uIG9mIHRoZSBkaWZmZXJlbmNlcyBhbmQgdXNpbmcgdGhlc2UgZGlmZmVyZW50IGVuZ2luZXMgd2l0aCBgcGFyc25pcGAuCgpXZSB3aWxsIGRvIHNvIGJ5IHVzaW5nIHRoZSBgc2V0X2VuZ2luZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHBhcnNuaXBgIHBhY2thZ2UuCgpgYGB7cn0KbG1fUE1fbW9kZWwgPC0gCiAgUE1fbW9kZWwgICU+JQogIHBhcnNuaXA6OnNldF9lbmdpbmUoImxtIikKCmxtX1BNX21vZGVsCmBgYAoKSW4gc29tZSBjYXNlcyBzb21lIHBhY2thZ2VzIGNhbiBkbyBlaXRoZXIgY2xhc3NpZmljYXRpb24gb3IgcHJlZGljdGlvbiwgc28gaXQgaXMgYSBnb29kIGlkZWEgdG8gc3BlY2lmeSB3aGljaCBtb2RlIHlvdSBpbnRlbmQgdG8gcGVyZm9ybS4gCkhlcmUsIHdlIGFpbSB0byBwcmVkaWN0IHRoZSBhaXIgcG9sbHV0aW9uLiAKWW91IGNhbiBkbyB0aGlzIHdpdGggdGhlIGBzZXRfbW9kZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHBhcnNuaXBgIHBhY2thZ2UsIGJ5IHVzaW5nIGVpdGhlciBgc2V0X21vZGUoImNsYXNzaWZpY2F0aW9uIilgIG9yIGBzZXRfbW9kZSgicmVncmVzc2lvbiIpYC4KCmBgYHtyfQpsbV9QTV9tb2RlbCA8LSAKICBQTV9tb2RlbCAgJT4lCiAgcGFyc25pcDo6c2V0X2VuZ2luZSgibG0iKSAlPiUKICBzZXRfbW9kZSgicmVncmVzc2lvbiIpCgpsbV9QTV9tb2RlbApgYGAKCiMjIEZpdHRpbmcgdGhlIG1vZGVsCgpXZSBjYW4gIHVzZSB0aGUgYHBhcnNuaXBgIHBhY2thZ2Ugd2l0aCBhIG5ld2VyIHBhY2thZ2UgY2FsbGVkIGB3b3JrZmxvd3NgIHRvIGZpdCBvdXIgbW9kZWwuIAoKVGhlIGB3b3JrZmxvd3NgIHBhY2thZ2UgYWxsb3dzIHVzIHRvIGtlZXAgdHJhY2sgb2YgYm90aCBvdXIgcHJlLXByb2Nlc3Npbmcgc3RlcHMgYW5kIG91ciBtb2RlbCBzcGVjaWZpY2F0aW9uLiBJdCBhbHNvIGFsbG93cyB1cyB0byBpbXBsZW1lbnQgZmFuY2llciBvcHRpbWl6YXRpb25zIGluIGFuIGF1dG9tYXRlZCB3YXkgYW5kIGl0IGNhbiBhbHNvIGhhbmRsZSBwb3N0LXByb2Nlc3Npbmcgb3BlcmF0aW9ucy4gCgoKV2UgYmVnaW4gYnkgY3JlYXRpbmcgYSB3b3JrZmxvdyB1c2luZyB0aGUgYHdvcmtmbG93KClgIGZ1bmN0aW9uIGluIHRoZSBgd29ya2Zsb3dzYCBwYWNrYWdlLiAKCk5leHQsIHdlIHVzZSBgYWRkX3JlY2lwZSgpYCAob3VyIHByZS1wcm9jZXNzaW5nIHNwZWNpZmljYXRpb25zKSBhbmQgd2UgYWRkIG91ciBtb2RlbCB3aXRoIHRoZSBgYWRkX21vZGVsKClgIGZ1bmN0aW9uIC0tIGJvdGggZnVuY3Rpb25zIGZyb20gdGhlIGB3b3JrZmxvd3NgIHBhY2thZ2UuCgoqKk5vdGUqKjogV2UgZG8gbm90IG5lZWQgdG8gYWN0dWFsbHkgYHByZXAoKWAgb3VyIHJlY2lwZSBiZWZvcmUgdXNpbmcgd29ya2Zsb3dzIQoKSWYgeW91IHJlY2FsbCBgbm92ZWxfcmVjYCBpcyB0aGUgcmVjaXBlIHdlIHByZXZpb3VzbHkgY3JlYXRlZCB3aXRoIHRoZSBgcmVjaXBlc2AgcGFja2FnZSBhbmQgYGxtX1BNX21vZGVsYCB3YXMgY3JlYXRlZCB3aGVuIHdlIHNwZWNpZmllZCBvdXIgbW9kZWwgd2l0aCB0aGUgYHBhcnNuaXBgIHBhY2thZ2UuCkhlcmUsIHdlIGNvbWJpbmUgZXZlcnl0aGluZyB0b2dldGhlciBpbnRvIGEgd29ya2Zsb3cuIAoKYGBge3J9ClBNX3dmbG93IDwtd29ya2Zsb3dzOjp3b3JrZmxvdygpICU+JQogICAgICAgICAgIHdvcmtmbG93czo6YWRkX3JlY2lwZShub3ZlbF9yZWMpICU+JQogICAgICAgICAgIHdvcmtmbG93czo6YWRkX21vZGVsKGxtX1BNX21vZGVsKQpQTV93ZmxvdwpgYGAKCkFoLCBuaWNlLiAKTm90aWNlIGhvdyBpdCB0ZWxscyB1cyBhYm91dCBib3RoIG91ciBwcmUtcHJvY2Vzc2luZyBzdGVwcyBhbmQgb3VyIG1vZGVsIHNwZWNpZmljYXRpb25zLgoKTmV4dCwgd2UgInByZXBhcmUgdGhlIHJlY2lwZSIgKG9yIGVzdGltYXRlIHRoZSBwYXJhbWV0ZXJzKSBhbmQgZml0IHRoZSBtb2RlbCB0byBvdXIgdHJhaW5pbmcgZGF0YSBhbGwgYXQgb25jZS4gClByaW50aW5nIHRoZSBvdXRwdXQsIHdlIGNhbiBzZWUgdGhlIGNvZWZmaWNpZW50cyBvZiB0aGUgbW9kZWwuCgpgYGB7cn0KUE1fd2Zsb3dfZml0IDwtIHBhcnNuaXA6OmZpdChQTV93ZmxvdywgZGF0YSA9IHRyYWluX3BtKQpQTV93Zmxvd19maXQKYGBgCgoKPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gc2VlIHRoZSBzdGVwcyB0aGF0IHRoZSBgd29ya2Zsb3dzYCBwYWNrYWdlIHBlcmZvcm1zIHRoYXQgdXNlZCB0byBiZSByZXF1aXJlZCA8L3N1bW1hcnk+CgpQcmV2aW91c2x5LCB0aGUgcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgKGBqdWljZWRfdHJhaW5gKSwgYXMgb3Bwb3NlZCB0byB0aGUgcmF3IHRyYWluaW5nIGRhdGEsIHdvdWxkIGJlIHJlcXVpcmVkIHRvIGZpdCB0aGUgbW9kZWwuCgpJbiB0aGlzIGNhc2UsIHdlIHdvdWxkIGFjdHVhbGx5IGFsc28gbmVlZCB0byB3cml0ZSB0aGUgbW9kZWwgYWdhaW4hIApSZWNhbGwgdGhhdCBgaWRgIGFuZCBgZmlwc2AgYXJlIElEIHZhcmlhYmxlcyBhbmQgdGhhdCBgdmFsdWVzYCBpcyBvdXIgb3V0Y29tZSBvZiBpbnRlcmVzdCAodGhlIGFpciBwb2xsdXRpb24gbWVhc3VyZSBhdCBlYWNoIG1vbml0b3IpLiBJdCBpcyBuaWNlIHRoYXQgYHdvcmtmbG93c2Aga2VlcHMgdHJhY2sgb2YgdGhpcyEKCmBgYHtyfQpqdWljZWRfdHJhaW5fcmVhZHkgPC0ganVpY2VkX3RyYWluICU+JSAKICBzZWxlY3QoLWlkLCAtZmlwcykKClBNX2ZpdCA8LSBsbV9QTV9tb2RlbCAlPiUgCiAgcGFyc25pcDo6Zml0KHZhbHVlIH4uLCBkYXRhID0ganVpY2VkX3RyYWluX3JlYWR5KQpgYGAKCjwvZGV0YWlscz4KCiMjIEFzc2Vzc2luZyB0aGUgbW9kZWwgZml0CgpBZnRlciB3ZSBmaXQgb3VyIG1vZGVsLCB3ZSBjYW4gdXNlIHRoZSBgYnJvb21gIHBhY2thZ2UgdG8gbG9vayBhdCB0aGUgb3V0cHV0IGZyb20gdGhlIGZpdHRlZCBtb2RlbCBpbiBhbiBlYXN5L3RpZHkgd2F5LiAgIAoKVGhlIGB0aWR5KClgIGZ1bmN0aW9uIHJldHVybnMgYSB0aWR5IGRhdGEgZnJhbWUgd2l0aCBjb2VmZmljaWVudHMgZnJvbSB0aGUgbW9kZWwgKG9uZSByb3cgcGVyIGNvZWZmaWNpZW50KS4KCk1hbnkgb3RoZXIgYGJyb29tYCBmdW5jdGlvbnMgY3VycmVudGx5IG9ubHkgd29yayB3aXRoIGBwYXJzbmlwYCBvYmplY3RzLCBub3QgcmF3IGB3b3JrZmxvd3NgIG9iamVjdHMuIAoKSG93ZXZlciwgd2UgY2FuIHVzZSB0aGUgYHRpZHlgIGZ1bmN0aW9uIGlmIHdlIGZpcnN0IHVzZSB0aGUgYHB1bGxfd29ya2Zsb3dfZml0KClgIGZ1bmN0aW9uLgoKYGBge3J9CndmbG93b3V0cHV0IDwtIFBNX3dmbG93X2ZpdCAlPiUgCiAgcHVsbF93b3JrZmxvd19maXQoKSAlPiUgCiAgYnJvb206OnRpZHkoKSAKYGBgCgoKYGBge3J9CndmbG93b3V0cHV0CmBgYAoKV2UgaGF2ZSBmaXQgb3VyIG1vZGVsIG9uIG91ciB0cmFpbmluZyBkYXRhLCB3aGljaCBtZWFucyB3ZSBoYXZlIGNyZWF0ZWQgYSBtb2RlbCB0byBwcmVkaWN0IHZhbHVlcyBvZiBhaXIgcG9sbHV0aW9uIGJhc2VkIG9uIHRoZSBwcmVkaWN0b3JzIHRoYXQgd2UgaGF2ZSBpbmNsdWRlZC4gWWF5IQoKT25lIGxhc3QgdGhpbmcgYmVmb3JlIHdlIGxlYXZlIHRoaXMgc2VjdGlvbi4gCldlIG9mdGVuIGFyZSBpbnRlcmVzdGVkIGluIGdldHRpbmcgYSBzZW5zZSBvZiB3aGljaCB2YXJpYWJsZXMgYXJlIHRoZSBtb3N0IGltcG9ydGFudCBpbiBvdXIgbW9kZWwuIApXZSBjYW4gZXhwbG9yZSB0aGUgdmFyaWFibGUgaW1wb3J0YW5jZSB1c2luZyB0aGUgYHZpcCgpYCBmdW5jdGlvbiBvZiB0aGUgYHZpcGAgcGFja2FnZS4gClRoaXMgZnVuY3Rpb24gY3JlYXRlcyBhIGJhciBwbG90IG9mIHZhcmlhYmxlIGltcG9ydGFuY2Ugc2NvcmVzIGZvciBlYWNoIHByZWRpY3RvciB2YXJpYWJsZSAob3IgZmVhdHVyZSkgaW4gYSBtb2RlbC4gClRoZSBiYXIgcGxvdCBpcyBvcmRlcmVkIGJ5IGltcG9ydGFuY2UgKGhpZ2hlc3QgdG8gc21hbGxlc3QpLiAKCgpOb3RpY2UgYWdhaW4gdGhhdCB3ZSBuZWVkIHRvIHVzZSB0aGUgYHB1bGxfd29ya2Zsb3dfZml0KClgIGZ1bmN0aW9uLgoKTGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIHRvcCAxMCBjb250cmlidXRpbmcgdmFyaWFibGVzOgoKYGBge3J9ClBNX3dmbG93X2ZpdCAlPiUgCiAgcHVsbF93b3JrZmxvd19maXQoKSAlPiUgCiAgdmlwKG51bV9mZWF0dXJlcyA9IDEwKQpgYGAKClRoZSBzdGF0ZSBpbiB3aGljaCB0aGUgbW9uaXRvciB3YXMgbG9jYXRlZCBhbmQgdGhlIENNQVEgbW9kZWwgYW5kIHRoZSBhb2Qgc2F0ZWxsaXRlIGluZm9ybWF0aW9uIGFwcGVhciB0byBiZSB0aGUgbW9zdCBpbXBvcnRhbnQgZm9yIHByZWRpY3RpbmcgdGhlIGFpciBwb2xsdXRpb24gYXQgYSBnaXZlbiBtb25pdG9yLgoKIyMgTW9kZWwgcGVyZm9ybWFuY2UKCkluIHRoaXMgbmV4dCBzZWN0aW9uLCBvdXIgZ29hbCBpcyB0byBhc3Nlc3MgdGhlIG92ZXJhbGwgbW9kZWwgcGVyZm9ybWFuY2UuIApUaGUgd2F5IHdlIGRvIHRoaXMgaXMgdG8gY29tcGFyZSB0aGUgc2ltaWxhcml0eSBiZXR3ZWVuIHRoZSBwcmVkaWN0ZWQgZXN0aW1hdGVzIG9mIHRoZSBvdXRjb21lIHZhcmlhYmxlIHByb2R1Y2VkIGJ5IHRoZSBtb2RlbCBhbmQgdGhlIHRydWUgb3V0Y29tZSB2YXJpYWJsZSB2YWx1ZXMuIAoKSWYgeW91IHJlY2FsbCB0aGUgW1doYXQgaXMgbWFjaGluZSBsZWFybmluZz9dKCN3aGF0aXNtbCkgc2VjdGlvbiwgd2Ugc2hvd2VkIGhvdyB0byB0aGluayBhYm91dCBtYWNoaW5lIGxlYXJuaW5nIChNTCkgYXMgYW4gb3B0aW1pemF0aW9uIHByb2JsZW0gdGhhdCB0cmllcyB0byBtaW5pbWl6ZSB0aGUgZGlzdGFuY2UgYmV0d2VlbiBvdXIgcHJlZGljdGVkIG91dGNvbWUgJFxoYXR7WX0gPSBmKFgpJCBhbmQgYWN0dWFsIG91dGNvbWUgJFkkIHVzaW5nIG91ciBmZWF0dXJlcyAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykgJFgkIGFzIGlucHV0IHRvIGEgZnVuY3Rpb24gJGYkIHRoYXQgd2Ugd2FudCB0byBlc3RpbWF0ZS4gCgokJGQoWSAtIFxoYXR7WX0pJCQKCkFzIG91ciBnb2FsIGluIHRoaXMgc2VjdGlvbiBpcyB0byBhc3Nlc3Mgb3ZlcmFsbCBtb2RlbCBwZXJmb3JtYW5jZSwgd2Ugd2lsbCBub3cgdGFsayBhYm91dCBkaWZmZXJlbnQgZGlzdGFuY2UgbWV0cmljcyB0aGF0IHlvdSBjYW4gdXNlLiAKCkZpcnN0LCBsZXQncyBwdWxsIG91dCBvdXIgcHJlZGljdGVkIG91dGNvbWUgdmFsdWVzICRcaGF0e1l9ID0gZihYKSQgZnJvbSB0aGUgbW9kZWxzIHdlIGZpdCAodXNpbmcgZGlmZmVyZW50IGFwcHJvYWNoZXMpLiAKCgpgYGB7cn0Kd2ZfZml0IDwtIFBNX3dmbG93X2ZpdCAlPiUgCiAgcHVsbF93b3JrZmxvd19maXQoKQoKd2ZfZml0dGVkX3ZhbHVlcyA8LSBmaXR0ZWQod2ZfZml0W1siZml0Il1dKQpoZWFkKHdmX2ZpdHRlZF92YWx1ZXMpCmBgYAoKQWx0ZXJuYXRpdmVseSwgd2UgY2FuIGdldCB0aGUgZml0dGVkIHZhbHVlcyB1c2luZyB0aGUgYGF1Z21lbnQoKWAgZnVuY3Rpb24gb2YgdGhlIGBicm9vbWAgcGFja2FnZSB1c2luZyB0aGUgb3V0cHV0IGZyb20gYHdvcmtmbG93c2A6IAoKYGBge3J9CndmX2ZpdHRlZF92YWx1ZXMgPC0gCiAgYnJvb206OmF1Z21lbnQod2ZfZml0W1siZml0Il1dLCBkYXRhID0ganVpY2VkX3RyYWluKSAlPiUgCiAgc2VsZWN0KHZhbHVlLCAuZml0dGVkOi5zdGQucmVzaWQpCgpoZWFkKHdmX2ZpdHRlZF92YWx1ZXMpCgpgYGAKCk5vdGUgdGhhdCBiZWN1YXNlIHdlIHVzZSB0aGUgYWN0dWFsIHdvcmtmbG93IGhlcmUsIHdlIGNhbiAoYW5kIGFjdHVhbGx5IG5lZWQgdG8pIHVzZSB0aGUgcmF3IGRhdGEgaW5zdGVhZCBvZiB0aGUgcHJlLXByb2Nlc3NlZCBkYXRhLgoKYGBge3J9CnZhbHVlc19wcmVkX3RyYWluIDwtIAogIHByZWRpY3QoUE1fd2Zsb3dfZml0LCB0cmFpbl9wbSkgJT4lIAogIGJpbmRfY29scyh0cmFpbl9wbSAlPiUgc2VsZWN0KHZhbHVlLCBmaXBzLCBjb3VudHksIGlkKSkgCgp2YWx1ZXNfcHJlZF90cmFpbgoKYGBgCgojIyMgVmlzdWFsaXppbmcgbW9kZWwgcGVyZm9ybWFuY2UKCk5vdywgd2UgY2FuIGNvbXBhcmUgdGhlIHByZWRpY3RlZCBvdXRjb21lIHZhbHVlcyAob3IgZml0dGVkIHZhbHVlcykgJFxoYXR7WX0kIHRvIHRoZSBhY3R1YWwgb3V0Y29tZSB2YWx1ZXMgJFkkIHRoYXQgd2Ugb2JzZXJ2ZWQ6IAoKYGBge3J9CndmX2ZpdHRlZF92YWx1ZXMgJT4lIAogIGdncGxvdChhZXMoeCA9ICB2YWx1ZSwgeSA9IC5maXR0ZWQpKSArIAogIGdlb21fcG9pbnQoKSArIAogIHhsYWIoImFjdHVhbCBvdXRjb21lIHZhbHVlcyIpICsgCiAgeWxhYigicHJlZGljdGVkIG91dGNvbWUgdmFsdWVzIikKYGBgCgpPSywgc28gb3VyIHJhbmdlIG9mIHRoZSBwcmVkaWN0ZWQgb3V0Y29tZSB2YWx1ZXMgYXBwZWFycyB0byBiZSBzbWFsbGVyIHRoYW4gdGhlIHJlYWwgdmFsdWVzLiAKV2UgY291bGQgcHJvYmFibHkgZG8gYSBiaXQgYmV0dGVyLgoKIyMjIFF1YW50aWZ5aW5nIG1vZGVsIHBlcmZvcm1hbmNlIAoKTmV4dCwgbGV0J3MgdXNlIGRpZmZlcmVudCBkaXN0YW5jZSBmdW5jdGlvbnMgJGQoXGNkb3QpJCB0byBhc3Nlc3MgaG93IGZhciBvZmYgb3VyIHByZWRpY3RlZCBvdXRjb21lICRcaGF0e1l9ID0gZihYKSQgYW5kIGFjdHVhbCBvdXRjb21lICRZJCB2YWx1ZXMgYXJlIGZyb20gZWFjaCBvdGhlcjogCgokJGQoWSAtIFxoYXR7WX0pJCQKCkFzIG1lbnRpb25lZCwgdGhlcmUgYXJlIGVudGlyZSBzY2hvbGFybHkgZmllbGRzIG9mIHJlc2VhcmNoIGRlZGljYXRlZCB0byBpZGVudGlmeWluZyBkaWZmZXJlbnQgZGlzdGFuY2UgbWV0cmljcyAkZChcY2RvdCkkIGZvciBtYWNoaW5lIGxlYXJuaW5nIGFwcGxpY2F0aW9ucy4gCkhvd2V2ZXIsIHdoZW4gcGVyZm9ybWluZyBwcmVkaWN0aW9uIHdpdGggYSBjb250aW51b3VzIG91dGNvbWUgJFkkLCBhIGZldyBvZiB0aGUgbW9zdGx5IGNvbW1vbmx5IHVzZWQgZGlzdGFuY2UgbWV0cmljcyBhcmU6IAoKMS4gbWVhbiBhYnNvbHV0ZSBlcnJvciAoYG1hZWApICAKCiQkTUFFID0gXGZyYWN7XHN1bV97aT0xfV57bn17KHxcaGF0e3lfdH0tIHlfdHwpfV4yfXtufSQkCgoKMi4gUiBzcXVhcmVkIGVycm9yIChgcnNxYCkgLS0gdGhpcyBpcyBhbHNvIGtub3duIGFzIHRoZSBjb2VmZmljaWVudCBvZiBkZXRlcm1pbmF0aW9uIHdoaWNoIGlzIHRoZSBzcXVhcmVkIGNvcnJlbGF0aW9uIGJldHdlZW4gdHJ1dGggYW5kIGVzdGltYXRlCgpUaGlzIGlzIGNhbGN1bGF0ZWQgYW5kIDEgbWludXMgdGhlIGZyYWN0aW9uIG9mIHRoZSByZXNpZHVhbCBzdW0gb2Ygc3F1YXJlcyAoJFNTX3JlcyQpIGJ5IHRoZSB0b3RhbCBzdW0gb2Ygc3F1YXJlcyAoJFNTX3RvdCQpCgoKJCRSU1EgPSBSXjIgPSAxIC0gXGZyYWN7U1NyZXN9e1NTdG90fSQkCgokJFNTX3t0b3R9ID0gXHN1bV97aT0xfV57bn17KHlfaS0gXGJhcnt5fSl9XjIkJApUaGUgdG90YWwgc3VtIG9mIHNxdWFyZXMgaXMgcHJvcG9ydGlvbmFsIHRvIHRoZSB2YXJpYW5jZSBvZiB0aGUgZGF0YS4gSXQgaXMgY2FsY3VsYXRlZCBhcyB0aGUgc3VtIG9mIGVhY2ggIHRydWUgdmFsdWUgZnJvbSB0aGUgbWVhbiB0cnVlIHZhbHVlICgkXGJhcnt5fSQpLgoKJCRTU197cmVzfSA9IFxzdW1fe2k9MX1ee259eyh5X2ktIFxoYXR7eV9pfSl9XjIkJAoKVGhlIHN1bSBvZiBzcXVhcmVzIG9mIHJlc2lkdWFscyBpcyBjYWxjdWxhdGVkIGFzIHRoZSBzdW0gb2YgZWFjaCBwcmVkaWN0ZWQgdmFsdWUgKCRcaGF0e3lfaX0kIG9yIHNvbWV0aW1lcyAkZl9pJCkgZnJvbSB0aGUgdHJ1ZSB2YWx1ZSAoJHlfaSQpLiAKCgozLiBbcm9vdCBtZWFuIHNxdWFyZWQgZXJyb3JdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1Jvb3QtbWVhbi1zcXVhcmVfZGV2aWF0aW9uKXt0YXJnZXQ9Il9ibGFuayJ9IChgcm1zZWApICAgCgokJFJNU0UgPSBcc3FydHtcZnJhY3tcc3VtX3tpPTF9XntufXsoXGhhdHt5X3R9LSB5X3QpfV4yfXtufX0kJAoKCgoKT25lIHdheSB0byBjYWxjdWxhdGUgdGhlc2UgbWV0cmljcyB3aXRoaW4gdGhlIGB0aWR5bW9kZWxzYCBmcmFtZXdvcmsgaXMgdG8gdXNlIHRoZSBgeWFyZHN0aWNrYCBwYWNrYWdlIHVzaW5nIHRoZSBgbWV0cmljcygpYCBmdW5jdGlvbi4gCgpgYGB7cn0KeWFyZHN0aWNrOjptZXRyaWNzKHdmX2ZpdHRlZF92YWx1ZXMsIAogICAgICAgICAgICAgICAgICAgdHJ1dGggPSB2YWx1ZSwgZXN0aW1hdGUgPSAuZml0dGVkKQpgYGAKCkFsdGVybmF0aXZlbHkgaWYgeW91IG9ubHkgd2FudGVkIG9uZSBtZXRyaWMgeW91IGNvdWxkIHVzZSB0aGUgYG1hZSgpYCwgYHJzcSgpYCwgb3IgYHJtc2UoKWAgZnVuY3Rpb25zLCByZXNwZWN0aXZlbHkuIAoKYGBge3J9CnlhcmRzdGljazo6bWFlKHdmX2ZpdHRlZF92YWx1ZXMsIAogICAgICAgICAgICAgICB0cnV0aCA9IHZhbHVlLCBlc3RpbWF0ZSA9IC5maXR0ZWQpCmBgYAoKIyMgQ3Jvc3MgdmFsaWRhdGlvbgoKVW50aWwgbm93IHdlIGhhdmUgdXNlZCBldmVyeXRoaW5nIGluIG91ciAidHJhaW5pbmciIGRhdGFzZXQgKGFuZCBoYXZlIG5vdCB0b3VjaGVkIHRoZSAidGVzdGluZyIgZGF0YXNldCkgZnJvbSB0aGUgYHJzYW1wbGVgIHBhY2thZ2UgdG8gYnVpbGQgb3VyIG1hY2hpbmUgbGVhcm5pbmcgKE1MKSBtb2RlbCAkXGhhdHtZfSA9IGYoWCkkIChvciB0byBlc3RpbWF0ZSAkZiQgdXNpbmcgdGhlIGZlYXR1cmVzIG9yIHByZWRpY3RvciB2YXJpYWJsZSAkWCQpLiAKCkhlcmUsIHdlIHRha2UgbW92ZSB0aGlzIGJleW9uZCB0aGUgc2ltcGxlIHNwbGl0IGludG8gdHJhaW5pbmcgYW5kIHRlc3RpbmcgZGF0YSBzZXRzLiAKV2Ugd2lsbCBhZ2FpbiB1c2UgdGhlIGByc2FtcGxlYCBwYWNrYWdlIGFnYWluIGluIG9yZGVyIHRvIGZ1cnRoZXIgaW1wbGVtZW50IHdoYXQgYXJlIGNhbGxlZCBbY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3MtdmFsaWRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gdGVjaG5pcXVlcy4gVGhpcyBpcyBhbHNvIGNhbGxlZCAqKnJlLXNhbXBsaW5nKiogb3IgKipyZXBhcnRpb25pbmcqKi4gIAoKKipOb3RlKio6IHdlIGFyZSBub3QgYWN0dWFsbHkgZ2V0dGluZyBuZXcgc2FtcGxlcyBmcm9tIHRoZSB1bmRlcmx5aW5nIGRpc3RyaWJ1dGlvbiBzbyB0aGUgdGVybSByZS1zYW1wbGluZyBpcyBhIGJpdCBvZiBhIG1pc25vbWVyLgoKW0Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXZhbGlkYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IHNwbGl0cyBvdXIgdHJhaW5pbmcgZGF0YSBpbnRvIG11bHRpcGxlIHRyYWluaW5nIGRhdGEgc2V0cyB0byBhbGxvdyBmb3IgYSBkZWVwZXIgYXNzZXNzbWVudCBvZiB0aGUgYWNjdXJhY3kgb2YgdGhlIG1vZGVsLgoKSGVyZSBpcyBhIHZpc3VhbGl6YXRpb24gb2YgdGhlIGNvbmNlcHQgZm9yIGNyb3NzIHZhbGlkYXRpb24vcmVzYW1wbGluZy9yZXBhcnRpdGlvbmluZyBmcm9tIFtNYXggS3Vobl0oaHR0cHM6Ly9yZXNvdXJjZXMucnN0dWRpby5jb20vYXV0aG9ycy9tYXgta3Vobil7dGFyZ2V0PSJfYmxhbmsifToKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwicmVzYW1wbGluZy5wbmciKSkKYGBgCgpUZWNobmljYWxseSBjcmVhdGluZyBvdXIgdGVzdGluZyBhbmQgdHJhaW5pbmcgc2V0IG91dCBvZiBvdXIgb3JpZ2luYWwgdHJhaW5pbmcgZGF0YSBpcyBzb21ldGltZXMgY29uc2lkZXJlZCBhIGZvcm0gb2YgW2Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXZhbGlkYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9LCBjYWxsZWQgdGhlIGhvbGRvdXQgbWV0aG9kLiAKVGhlIHJlYXNvbiB3ZSBkbyB0aGlzIGl0IHNvIHdlIGNhbiBnZXQgYSBiZXR0ZXIgc2Vuc2Ugb2YgdGhlIGFjY3VyYWN5IG9mIG91ciBtb2RlbCB1c2luZyBkYXRhIHRoYXQgd2UgZGlkIG5vdCB0cmFpbiBpdCBvbi4gCgpIb3dldmVyLCB3ZSBjYW4gYWN0dWFsbHkgZG8gYSBiZXR0ZXIgam9iIG9mIG9wdGltaXppbmcgb3VyIG1vZGVsIGZvciBhY2N1cmFjeSBpZiB3ZSBhbHNvIHBlcmZvcm0gYW5vdGhlciB0eXBlIG9mIFtjcm9zcyB2YWxpZGF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Dcm9zcy12YWxpZGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSBvbiB0aGUgbmV3bHkgZGVmaW5lZCB0cmFpbmluZyBzZXQgdGhhdCB3ZSBqdXN0IGNyZWF0ZWQuIApUaGVyZSBhcmUgbWFueSBbY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3MtdmFsaWRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gbWV0aG9kcyBhbmQgbW9zdCBjYW4gYmUgZWFzaWx5IGltcGxlbWVudGVkIHVzaW5nIGByc2FtcGxlYCBwYWNrYWdlLiAKSGVyZSwgd2Ugd2lsbCB1c2UgYSB2ZXJ5IHBvcHVsYXIgbWV0aG9kIGNhbGxlZCBlaXRoZXIgW2stZm9sZCBvciB2LWZvbGQgY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly9tYWNoaW5lbGVhcm5pbmdtYXN0ZXJ5LmNvbS9rLWZvbGQtY3Jvc3MtdmFsaWRhdGlvbi8pe3RhcmdldD0iX2JsYW5rIn0uIAoKVGhpcyBtZXRob2QgaW52b2x2ZXMgZXNzZW50aWFsbHkgcHJlZm9ybWluZyB0aGUgaG9sZCBvdXQgbWV0aG9kIGl0ZXJhdGl2ZWx5IHdpdGggdGhlIHRyYWluaW5nIGRhdGEuIAoKRmlyc3QsIHRoZSB0cmFpbmluZyBzZXQgaXMgZGl2aWRlZCBpbnRvICR2JCAob3Igb2Z0ZW4gY2FsbGVkIGNhbGxlZCAkayQpIGVxdWFsbHkgc2l6ZWQgc21hbGxlciBwaWVjZXMuIAoKTmV4dCwgdGhlIG1vZGVsIGlzIHRyYWluZWQgb24gdGhlIG1vZGVsIG9uICR2JC0xIHN1YnNldHMgb2YgdGhlIGRhdGEgaXRlcmF0aXZlbHkgKHJlbW92aW5nIGEgZGlmZmVyZW50ICR2JCB1bnRpbCBhbGwgcG9zc2libGUgJHYkLTEgc2V0cyBoYXZlIGJlZW4gZXZhbHVhdGVkKSB0byBnZXQgYSBzZW5zZSBvZiB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIG1vZGVsLiAKVGhpcyBpcyByZWFsbHkgdXNlZnVsIGZvciBmaW5lIHR1bmluZyBzcGVjaWZpYyBhc3BlY3RzIG9mIHRoZSBtb2RlbCBpbiBhIHByb2Nlc3MgY2FsbGVkIG1vZGVsIHR1bmluZywgd2hpY2ggd2Ugd2lsbCBsZWFybiBhYm91dCBpbiB0aGUgbmV4dCBzZWN0aW9uLiAKCkhlcmUgaXMgYSB2aXN1YWxpemF0aW9uIG9mIGhvdyB0aGUgZm9sZHMgYXJlIGNyZWF0ZWQ6CgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJ2Zm9sZC5wbmciKSkKYGBgCgoqKk5vdGUqKjogUGVvcGxlIHR5cGljYWxseSBpZ25vcmUgc3BhdGlhbCBkZXBlbmRlbmNlIHdpdGggY3Jvc3MgdmFsaWRhdGlvbiBvZiBhaXIgcG9sbHV0aW9uIG1vbml0b3JpbmcgZGF0YSBpbiB0aGUgYWlyIHBvbGx1dGlvbiBmaWVsZCwgc28gd2Ugd2lsbCBkbyB0aGUgc2FtZS4gIEhvd2V2ZXIsIGl0IG1pZ2h0IG1ha2Ugc2Vuc2UgdG8gbGVhdmUgb3V0IGJsb2NrcyBvZiBtb25pdG9ycyByYXRoZXIgdGhhbiAgcmFuZG9tIGluZGl2aWR1YWwgbW9uaXRvcnMgdG8gaGVscCBhY2NvdW50IGZvciBzb21lIHNwYXRpYWwgZGVwZW5kZW5jZS4KCiMjIyBDcmVhdGluZyB0aGUgJHYkLWZvbGRzIHVzaW5nIGByc2FtcGxlYAoKVGhlIFtgdmZvbGRfY3YoKWBdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcnNhbXBsZS9yZWZlcmVuY2UvdmZvbGRfY3YuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBmdW5jdGlvbiBvZiB0aGUgYHJzYW1wbGVgIHBhY2thZ2UgY2FuIGJlIHVzZWQgdG8gcGFyc2UgdGhlIHRyYWluaW5nIGRhdGEgaW50byBmb2xkcyBmb3IgJHYkLWZvbGQgY3Jvc3MgdmFsaWRhdGlvbi4KCi0gVGhlIGB2YCBhcmd1bWVudCBzcGVjaWZpZXMgdGhlIG51bWJlciBvZiBmb2xkcyB0byBjcmVhdGUuCi0gVGhlIGByZXBlYXRzYCBhcmd1bWVudCBzcGVjaWZpZXMgaWYgYW55IHNhbXBsZXMgc2hvdWxkIGJlIHJlcGVhdGVkIGFjcm9zcyBmb2xkcyAtIGRlZmF1bHQgaXMgYEZBTFNFYAotIFRoZSBgc3RyYXRhYCBhcmd1bWVudCBzcGVjaWZpZXMgYSB2YXJpYWJsZSB0byBzdHJhdGlmeSBzYW1wbGVzIGFjcm9zcyBmb2xkcyAtIGp1c3QgbGlrZSBpbiBgaW5pdGlhbF9zcGxpdCgpYC4KCkFnYWluLCBiZWNhdXNlIHRoZXNlIGFyZSBjcmVhdGVkIGF0IHJhbmRvbSwgd2UgbmVlZCB0byB1c2UgdGhlIGJhc2UgYHNldC5zZWVkKClgIGZ1bmN0aW9uIGluIG9yZGVyIHRvIG9idGFpbiB0aGUgc2FtZSByZXN1bHRzIGVhY2ggdGltZSB3ZSBrbml0IHRoaXMgZG9jdW1lbnQuIApHZW5lcmFsbHkgc3BlYWtpbmcgdXNpbmcgMTAgZm9sZHMgaXMgZ29vZCBwcmFjdGljZSwgYnV0IHRoaXMgZGVwZW5kcyBvbiB0aGUgdmFyaWFiaWxpdHkgd2l0aGluIHlvdXIgZGF0YS4gCldlIGFyZSBnb2luZyB0byB1c2UgNCBmb3IgdGhlIHNha2Ugb2YgZXhwZWRpZW5jeS4gCgpgYGB7cn0Kc2V0LnNlZWQoMTIzNCkKdmZvbGRfcG0gPC0gcnNhbXBsZTo6dmZvbGRfY3YoZGF0YSA9IHRyYWluX3BtLCB2ID0gNCkKdmZvbGRfcG0KcHVsbCh2Zm9sZF9wbSwgc3BsaXRzKQpgYGAKCk5vdyB3ZSBjYW4gc2VlIHRoYXQgd2UgaGF2ZSBjcmVhdGVkIDQgZm9sZHMgb2YgdGhlIGRhdGEgYW5kIHdlIGNhbiBzZWUgaG93IG1hbnkgdmFsdWVzIHdlcmUgc2V0IGFzaWRlIGZvciB0ZXN0aW5nIChjYWxsZWQgYXNzZXNzaW5nIGZvciBjcm9zcyB2YWxpZGF0aW9uIHNldHMpIGFuZCB0cmFpbmluZyAoY2FsbGVkIGFuYWx5c2lzIGZvciBjcm9zcyB2YWxpZGF0aW9uIHNldHMpIHdpdGhpbiBlYWNoIGZvbGQuCgpPbmNlIHRoZSBmb2xkcyBhcmUgY3JlYXRlZCB0aGV5IGNhbiBiZSB1c2VkIHRvIGV2YWx1YXRlIHBlcmZvcm1hbmNlIGJ5IGZpdHRpbmcgdGhlIG1vZGVsIHRvIGVhY2ggb2YgdGhlIHJlLXNhbXBsZXMgdGhhdCB3ZSBjcmVhdGVkOgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiY3Jvc3NfdmFsaWRhdGlvbi5wbmciKSkKYGBgCgojIyMgQXNzZXNzaW5nIG1vZGVsIHBlcmZvcm1hbmNlIG9uICR2JC1mb2xkcyB1c2luZyBgdHVuZWAKCldlIGNhbiBmaXQgdGhlIG1vZGVsIHRvIG91ciBjcm9zcyB2YWxpZGF0aW9uIGZvbGRzIHVzaW5nIHRoZSBgZml0X3Jlc2FtcGxlcygpYCBmdW5jdGlvbiBvZiB0aGUgYHR1bmVgIHBhY2thZ2UsIGJ5IHNwZWNpZnlpbmcgb3VyIGB3b3JrZmxvd2Agb2JqZWN0IGFuZCB0aGUgY3Jvc3MgdmFsaWRhdGlvbiBmb2xkIG9iamVjdCB3ZSBqdXN0IGNyZWF0ZWQuIApTZWUgW2hlcmVdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vdHVuZS9yZWZlcmVuY2UvZml0X3Jlc2FtcGxlcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGluZm9ybWF0aW9uLgoKCmBgYHtyfQpyZXNhbXBsZV9maXQgPC0gdHVuZTo6Zml0X3Jlc2FtcGxlcyhQTV93ZmxvdywgdmZvbGRfcG0pCmBgYAoKV2UgY2FuIG5vdyB0YWtlIGEgbG9vayBhdCB2YXJpb3VzIHBlcmZvcm1hbmNlIG1ldHJpY3MgYmFzZWQgb24gdGhlIGZpdCBvZiBvdXIgY3Jvc3MgdmFsaWRhdGlvbiAicmVzYW1wbGVzIi4gClRvIGRvIHRoaXMgd2Ugd2lsbCB1c2UgdGhlIGBzaG93X2Jlc3QoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlLgoKYGBge3J9CnR1bmU6OnNob3dfYmVzdChyZXNhbXBsZV9maXQsIG1ldHJpYyA9ICJybXNlIikKYGBgCgpIZXJlIHdlIGNhbiBzZWUgdGhlIG1lYW4gYFJNU0VgIHZhbHVlIGFjcm9zcyBhbGwgZm91ciBmb2xkcy4gVGhlIGZ1bmN0aW9uIGlzIGNhbGxlZCBgc2hvd19iZXN0KClgIGJlY2F1c2UgaXQgaXMgYWxzbyB1c2VkIGZvciBtb2RlbCB0dW5pbmcgYW5kIGl0IHdpbGwgc2hvdyB0aGUgcGFyYW1ldGVyIGNvbWJpbmF0aW9uIHdpdGggdGhlIGJlc3QgcGVyZm9ybWFuY2UsIHdlIHdpbGwgZGlzY3VzcyB0aGlzIG1vcmUgbGF0ZXIgaW4gdGhlIGNhc2Ugc3R1ZHkuCgoKIyAqKkRhdGEgQW5hbHlzaXMqKgoqKioKCkluIHRoZSBwcmV2aW91cyBzZWN0aW9uLCB3ZSBkZW1vbnN0cmF0ZWQgaG93IHRvIGJ1aWxkIGEgbWFjaGluZSBsZWFybmluZyBtb2RlbCAoc3BlY2lmaWNhbGx5IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwpIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbiB3aXRoIHRoZSBgdGlkeW1vZGVsc2AgZnJhbWV3b3JrLiAKCkluIHRoZSBuZXh0IGZldyBzZWN0aW9uLCB3ZSB3aWxsIGRlbW9uc3RyYXRlIGFub3RoZXIgbWFjaGluZSBsZWFybmluZyBtb2RlbC4gCgoKIyMgUmFuZG9tIEZvcmVzdAoKTm93LCB3ZSBhcmUgZ29pbmcgdG8gcHJlZGljdCBvdXIgb3V0Y29tZSB2YXJpYWJsZSAoYWlyIHBvbGx1dGlvbikgdXNpbmcgYSBkZWNpc2lvbiB0cmVlIG1ldGhvZCBjYWxsZWQgW3JhbmRvbSBmb3Jlc3RdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1JhbmRvbV9mb3Jlc3Qpe3RhcmdldD0iX2JsYW5rIn0uCgpBIFtkZWNpc2lvbiB0cmVlXShodHRwczovL21lZGl1bS5jb20vZ3JleWF0b20vZGVjaXNpb24tdHJlZXMtYS1zaW1wbGUtd2F5LXRvLXZpc3VhbGl6ZS1hLWRlY2lzaW9uLWRjNTA2YTQwM2FlYil7dGFyZ2V0PSJfYmxhbmsifSBpcyBhIHRvb2wgdG8gcGFydGl0aW9uIGRhdGEgb3IgYW55dGhpbmcgcmVhbGx5LCBiYXNlZCBvbiBhIHNlcmllcyBvZiBzZXF1ZW50aWFsIChvZnRlbiBiaW5hcnkpIGRlY2lzaW9ucywgd2hlcmUgdGhlIGRlY2lzaW9ucyBhcmUgY2hvc2VuIGJhc2VkIG9uIHRoZWlyIGFiaWxpdHkgdG8gb3B0aW1hbGx5IHNwbGl0IHRoZSBkYXRhLgoKSGVyZSB5b3UgY2FuIHNlZSBhIHNpbXBsZSBleGFtcGxlOgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vbWlyby5tZWRpdW0uY29tL21heC8xMDAwLzEqTE1vSm1YQ3NRbGNpR1RFeW9TTjM5Zy5qcGVnIikKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS91bmRlcnN0YW5kaW5nLXJhbmRvbS1mb3Jlc3QtNTgzODFlMDYwMmQyKXt0YXJnZXQ9Il9ibGFuayJ9CgpJbiB0aGUgY2FzZSBvZiBbcmFuZG9tIGZvcmVzdF0oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL2RlY2lzaW9uLXRyZWUtZW5zZW1ibGVzLWJhZ2dpbmctYW5kLWJvb3N0aW5nLTI2NmE4YmE2MGZkOSl7dGFyZ2V0PSJfYmxhbmsifSwgbXVsdGlwbGUgZGVjaXNpb24gdHJlZXMgYXJlIGNyZWF0ZWQgLSBoZW5jZSB0aGUgbmFtZSBmb3Jlc3QsIGFuZCBlYWNoIHRyZWUgaXMgYnVpbHQgdXNpbmcgYSByYW5kb20gc3Vic2V0IG9mIHRoZSB0cmFpbmluZyBkYXRhICh3aXRoIHJlcGxhY2VtZW50KSAtIGhlbmNlIHRoZSBmdWxsIG5hbWUgcmFuZG9tIGZvcmVzdC4gVGhpcyByYW5kb20gYXNwZWN0IGhlbHBzIHRvIGtlZXAgdGhlIGFsZ29yaXRobSBmcm9tIG92ZXJmaXR0aW5nIHRoZSBkYXRhLgoKVGhlIG1lYW4gb2YgdGhlIHByZWRpY3Rpb25zIGZyb20gZWFjaCBvZiB0aGUgdHJlZXMgaXMgdXNlZCBpbiB0aGUgZmluYWwgb3V0cHV0LgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vbWlyby5tZWRpdW0uY29tL21heC8xNDAwLzAqZl9xUVBGcGRvZldHTFFxYy5wbmciKQpgYGAKCgpJbiBvdXIgY2FzZSwgd2UgYXJlIGdvaW5nIHRvIHVzZSB0aGUgcmFuZG9tIGZvcmVzdCBtZXRob2Qgb2YgdGhlIHRoZSBgcmFuZG9tRm9yZXN0YCBwYWNrYWdlLiAKClRoaXMgcGFja2FnZSBpcyBjdXJyZW50bHkgbm90IGNvbXBhdGlibGUgd2l0aCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgdGhhdCBoYXZlIG1vcmUgdGhhbiA1MyBsZXZlbHMuIFNlZSBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JhbmRvbUZvcmVzdC9ORVdTKSBmb3IgdGhlIGRvY3VtZW50YXRpb24gYWJvdXQgd2hlbiB0aGlzIHdhcyB1cGRhdGVkIGZyb20gMjUgbGV2ZWxzLiBUaHVzIHdlIHdpbGwgcmVtb3ZlIHRoZSBgemN0YWAgIGFuZCBgY291bnR5YCB2YXJpYWJsZXMuCgpOb3RlIHRoYXQgdGhlIGBzdGVwX25vdmVsKClgIGZ1bmN0aW9uIGlzIG5lY2Vzc2FyeSBoZXJlIGZvciB0aGUgYHN0YXRlYCB2YXJpYWJsZSB0byBnZXQgYWxsIGNyb3NzIHZhbGlkYXRpb24gZm9sZHMgdG8gd29yaywgYmVjYXVzZSB0aGVyZSB3aWxsIGJlIGRpZmZlcmVudCBsZXZlbHMgaW5jbHVkZWQgaW4gZWFjaCBmb2xkIHRlc3QgYW5kIHRyYWluaW5nIHNldHMuIFRoZSBuZXcgbGV2ZWxzIGZvciBzb21lIG9mIHRoZSB0ZXN0IHNldHMgd291bGQgb3RoZXJ3aXNlIHJlc3VsdCBpbiBhbiBlcnJvci4KCkFjY29yZGluZyB0byB0aGUgW2RvY3VtZW50YXRpb25dKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy9yZWNpcGVzL3ZlcnNpb25zLzAuMS4xMy90b3BpY3Mvc3RlcF9ub3ZlbCkgZm9yIHRoZSBgcmVjaXBlc2AgcGFja2FnZToKCj4gc3RlcF9ub3ZlbCBjcmVhdGVzIGEgc3BlY2lmaWNhdGlvbiBvZiBhIHJlY2lwZSBzdGVwIHRoYXQgd2lsbCBhc3NpZ24gYSBwcmV2aW91c2x5IHVuc2VlbiBmYWN0b3IgbGV2ZWwgdG8gYSBuZXcgdmFsdWUuCgpgYGB7cn0KUkZfcmVjIDwtIHJlY2lwZSh0cmFpbl9wbSkgJT4lCiAgICB1cGRhdGVfcm9sZShldmVyeXRoaW5nKCksIG5ld19yb2xlID0gInByZWRpY3RvciIpJT4lCiAgICB1cGRhdGVfcm9sZSh2YWx1ZSwgbmV3X3JvbGUgPSAib3V0Y29tZSIpJT4lCiAgICB1cGRhdGVfcm9sZShpZCwgbmV3X3JvbGUgPSAiaWQgdmFyaWFibGUiKSAlPiUKICAgIHVwZGF0ZV9yb2xlKCJmaXBzIiwgbmV3X3JvbGUgPSAiY291bnR5IGlkIikgJT4lCiAgICBzdGVwX25vdmVsKCJzdGF0ZSIpICU+JQogICAgc3RlcF9zdHJpbmcyZmFjdG9yKCJzdGF0ZSIsICJjb3VudHkiLCAiY2l0eSIpICU+JQogICAgc3RlcF9ybSgiY291bnR5IikgJT4lCiAgICBzdGVwX3JtKCJ6Y3RhIikgJT4lCiAgICBzdGVwX2NvcnIoYWxsX251bWVyaWMoKSklPiUKICAgIHN0ZXBfbnp2KGFsbF9udW1lcmljKCkpCmBgYAoKVGhlIGByYW5kX2ZvcmVzdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHBhcnNuaXBgIHBhY2thZ2UgaGFzIHRocmVlIGltcG9ydGFudCBhcmd1bWVudHMgdGhhdCBhY3QgYXMgYW4gaW50ZXJmYWNlIGZvciB0aGUgZGlmZmVyZW50IHBvc3NpYmxlIGVuZ2luZXMgdG8gcGVyZm9ybSBhIHJhbmRvbSBmb3Jlc3QgYW5hbHlzaXM6CgoxLiBgbXRyeWAgLSBUaGUgbnVtYmVyIG9mIHByZWRpY3RvciB2YXJpYWJsZXMgKG9yIGZlYXR1cmVzKSB0aGF0IHdpbGwgYmUgcmFuZG9tbHkgc2FtcGxlZCBhdCBlYWNoIHNwbGl0IHdoZW4gY3JlYXRpbmcgdGhlIHRyZWUgbW9kZWxzLiBUaGUgZGVmYXVsdCBudW1iZXIgZm9yIHJlZ3Jlc3Npb24gYW5hbHlzZXMgaXMgdGhlIG51bWJlciBvZiBwcmVkaWN0b3JzIGRpdmlkZWQgYnkgMy4gCjIuIGBtaW5fbmAgLSBUaGUgbWluaW11bSBudW1iZXIgb2YgZGF0YSBwb2ludHMgaW4gYSBub2RlIHRoYXQgYXJlIHJlcXVpcmVkIGZvciB0aGUgbm9kZSB0byBiZSBzcGxpdCBmdXJ0aGVyLgozLiBgdHJlZXNgIC0gdGhlIG51bWJlciBvZiB0cmVlcyBpbiB0aGUgZW5zZW1ibGUKCldlIHdpbGwgc3RhcnQgYnkgdHJ5aW5nIGFuIGBtdHJ5YCB2YWx1ZSBvZiAxMCBhbmQgYSBgbWluX25gIHZhbHVlIG9mIDMuCgpOb3cgdGhhdCB3ZSBoYXZlIG91ciByZWNpcGUgKGBSRl9yZWNgKSwgbGV0J3Mgc3BlY2lmeSB0aGUgbW9kZWwgd2l0aCBgcmFuZF9mb3Jlc3QoKWAgZnJvbSBgcGFyc25pcGAuCgpgYGB7cn0KUE10cmVlX21vZGVsIDwtIAogIHBhcnNuaXA6OnJhbmRfZm9yZXN0KG10cnkgPSAxMCwgbWluX24gPSAzKQpQTXRyZWVfbW9kZWwKYGBgCgpOZXh0LCB3ZSBzZXQgdGhlIGVuZ2luZSBhbmQgbW9kZToKCk5vdGUgdGhhdCB5b3UgY291bGQgYWxzbyB1c2UgdGhlIGByYW5nZXJgIG9yIGBzcGFya2AgcGFja2FnZXMgaW5zdGVhZCBvZiBgcmFuZG9tRm9yZXN0YC4KSWYgeW91IHdlcmUgdG8gdXNlIHRoZSBgcmFuZ2VyYCBwYWNrYWdlIHRvIGltcGxlbWVudCB0aGUgcmFuZG9tIGZvcmVzdCBhbmFseXNpcyB5b3Ugd291bGQgbmVlZCB0byBzcGVjaWZ5IGFuIGBpbXBvcnRhbmNlYCBhcmd1bWVudCB0byBiZSBhYmxlIHRvIGV2YWx1YXRlIHByZWRpY3RvciBpbXBvcnRhbmNlLiAgVGhlIG9wdGlvbnMgYXJlIGBpbXB1cml0eWAgb3IgYHBlcm11dGF0aW9uYC4KClRoZXNlIG90aGVyIHBhY2thZ2VzIGhhdmUgZGlmZmVyZW50IGFkdmFudGFnZXMgYW5kIGRpc2FkdmFudGFnZXMtIGZvciBleGFtcGxlIGByYW5nZXJgIGFuZCBgc3BhcmtgIGFyZSBub3QgYXMgbGltaXRpbmcgZm9yIHRoZSBudW1iZXIgb2YgY2F0ZWdvcmllcyBmb3IgY2F0ZWdvcmljYWwgdmFyaWFibGVzLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBzZWUgdGhlaXIgZG9jdW1lbnRhdGlvbjogW2hlcmVdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yYW5nZXIvcmFuZ2VyLnBkZikgZm9yIHJhbmdlciwgW2hlcmVdKGh0dHA6Ly9zcGFyay5hcGFjaGUub3JnL2RvY3MvbGF0ZXN0L21sbGliLWVuc2VtYmxlcy5odG1sI3JhbmRvbS1mb3Jlc3RzKSBmb3IgYHNwYXJrYCwgYW5kIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmFuZG9tRm9yZXN0L3JhbmRvbUZvcmVzdC5wZGYpIGZvciBgcmFuZG9tRm9yZXN0YC4KClNlZSBbaGVyZV0oaHR0cHM6Ly9wYXJzbmlwLnRpZHltb2RlbHMub3JnL3JlZmVyZW5jZS9yYW5kX2ZvcmVzdC5odG1sKSBmb3IgbW9yZSBkb2N1bWVudGF0aW9uIGFib3V0IGltcGxlbWVudGluZyB0aGVzZSBlbmdpbmUgb3B0aW9ucyB3aXRoIHRpZHltb2RlbHMuIE5vdGUgdGhhdCB0aGVyZSBhcmUgYWxzbyBbb3RoZXJdKGh0dHBzOi8vd3d3LmxpbmtlZGluLmNvbS9wdWxzZS9kaWZmZXJlbnQtcmFuZG9tLWZvcmVzdC1wYWNrYWdlcy1yLW1hZGh1ci1tb2RpLykgUiBwYWNrYWdlcyBmb3IgaW1wbGVtZW50aW5nIHJhbmRvbSBmb3Jlc3QgYWxnb3JpdGhtcywgYnV0IHRoZXNlIHRocmVlIHBhY2thZ2VzIChgcmFuZ2VyYCwgYHNwYXJrYCwgYW5kIGByYW5kb21Gb3Jlc3RgKSBhcmUgY3VycmVudGx5IGNvbXBhdGlibGUgd2l0aCBgdGlkeW1vZGVsc2AuCgpXZSBhbHNvIG5lZWQgdG8gc3BlY2lmeSB3aXRoIHRoZSBgc2V0X21vZGUoKWAgZnVuY3Rpb24gdGhhdCBvdXIgb3V0Y29tZSB2YXJpYWJsZSAoYWlyIHBvbGx1dGlvbikgaXMgY29udGludW91cy4gCgpgYGB7cn0KClJGX1BNX21vZGVsIDwtIAogIFBNdHJlZV9tb2RlbCAlPiUKICBzZXRfZW5naW5lKCJyYW5kb21Gb3Jlc3QiKSAlPiUKICBzZXRfbW9kZSgicmVncmVzc2lvbiIpCgpSRl9QTV9tb2RlbApgYGAKClRoZW4sIHdlIHB1dCB0aGlzIGFsbCB0b2dldGhlciBpbnRvIGEgYHdvcmtmbG93YDogCgojIyMjIHsucmVjYWxsX2NvZGVfcXVlc3Rpb25fYmxvY2t9CjxiPjx1PiBRdWVzdGlvbiBPcHBvcnR1bml0eSA8L3U+PC9iPgoKU2VlIGlmIHlvdSBjYW4gY29tZSB1cCB3aXRoIHRoZSBjb2RlIHRvIGRvIHRoaXMuCgojIyMjCgoqKioKPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHJldmVhbCB0aGUgYW5zd2VyLiA8L3N1bW1hcnk+CgpgYGB7cn0KUkZfd2Zsb3cgPC0gd29ya2Zsb3dzOjp3b3JrZmxvdygpICU+JQogICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9yZWNpcGUoUkZfcmVjKSAlPiUKICAgICAgICAgICAgd29ya2Zsb3dzOjphZGRfbW9kZWwoUkZfUE1fbW9kZWwpCgpgYGAKPC9kZXRhaWxzPiAKKioqCgpgYGB7cn0KUkZfd2Zsb3cKYGBgCgoKRmluYWxseSwgd2UgZml0IHRoZSBkYXRhIHRvIHRoZSBtb2RlbDoKCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpEbyB5b3UgcmVjYWxsIGhvdyB0byBkbyB0aGlzPwoKIyMjIwoKKioqCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byByZXZlYWwgdGhlIGFuc3dlci4gPC9zdW1tYXJ5PgoKYGBge3J9ClJGX3dmbG93X2ZpdCA8LSBwYXJzbmlwOjpmaXQoUkZfd2Zsb3csIGRhdGEgPSB0cmFpbl9wbSkKYGBgCjwvZGV0YWlscz4gCioqKgoKYGBge3J9ClJGX3dmbG93X2ZpdApgYGAKCkxldCdzIHRha2UgYSBsb29rIGF0IHRoZSB0b3AgMTAgY29udHJpYnV0aW5nIHZhcmlhYmxlczoKCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpTZWUgaWYgeW91IGNhbiByZWNhbGwgaG93IHRvIGRvIHRoaXMuCgojIyMjCgpgYGB7ciwgZWNobyA9IEZBTFNFfQpSRl93Zmxvd19maXQgJT4lIAogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lIAogIHZpcChudW1fZmVhdHVyZXMgPSAxMCkKCmBgYAoKCioqKgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBhbnN3ZXIuIDwvc3VtbWFyeT4KCmBgYHtyfQpSRl93Zmxvd19maXQgJT4lIAogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lIAogIHZpcChudW1fZmVhdHVyZXMgPSAxMCkKYGBgCjwvZGV0YWlscz4KKioqCgoKSW50ZXJlc3RpbmchIEluIHRoZSBwcmV2aW91cyBtb2RlbCB0aGUgQ01BUSB2YWx1ZXMgYW5kIHRoZSBzdGF0ZSB3aGVyZSB0aGUgbW9uaXRvciB3YXMgbG9jYXRlZCB3ZXJlIGFsc28gdGhlIHRvcCB0d28gbW9zdCBpbXBvcnRhbnQsIGhvd2V2ZXIgcHJlZGljdG9ycyBhYm91dCBlZHVjYXRpb24gbGV2ZWxzIG9mIHRoZSBjb21tdW5pdGllcyB3aGVyZSB0aGUgbW9uaXRvciB3YXMgbG9jYXRlZCB3YXMgYW1vbmcgdGhlIHRvcCBtb3N0IGltcG9ydGFudC4gTm93IHdlIHNlZSB0aGF0IHBvcHVsYXRpb24gZGVuc2l0eSBhbmQgcHJveGltaXR5IHRvIHNvdXJjZXMgb2YgZW1pc3Npb25zIGFuZCByb2FkcyBhcmUgYW1vbmcgdGhlIHRvcCB0ZW4uCgoKTm93IGxldCdzIHRha2UgYSBsb29rIGF0IG1vZGVsIHBlcmZvcm1hbmNlIGJ5IGZpdHRpbmcgdGhlIGRhdGEgdXNpbmcgY3Jvc3MgdmFsaWRhdGlvbjoKCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpTZWUgaWYgeW91IGNhbiByZWNhbGwgaG93IHRvIGRvIHRoaXMuCgojIyMjCgoqKioKPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHJldmVhbCB0aGUgYW5zd2VyLiA8L3N1bW1hcnk+CgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpzZXQuc2VlZCg0NTYpCnJlc2FtcGxlX1JGX2ZpdCA8LSB0dW5lOjpmaXRfcmVzYW1wbGVzKFJGX3dmbG93LCB2Zm9sZF9wbSkKY29sbGVjdF9tZXRyaWNzKHJlc2FtcGxlX1JGX2ZpdCkKYGBgCgo8L2RldGFpbHM+CioqKgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Kc2V0LnNlZWQoNDU2KQpyZXNhbXBsZV9SRl9maXQgPC0gdHVuZTo6Zml0X3Jlc2FtcGxlcyhSRl93ZmxvdywgdmZvbGRfcG0pCmNvbGxlY3RfbWV0cmljcyhyZXNhbXBsZV9SRl9maXQpCmBgYAoKTm93IGxldCdzIGNvbXBhcmUgdGhlIHBlcmZvcm1hbmNlIG9mIHRoaXMgbW9kZWwgd2l0aCBvdXIgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWw6CgpgYGB7cn0KIyBvdXIgaW5pdGlhbCBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbDoKY29sbGVjdF9tZXRyaWNzKHJlc2FtcGxlX2ZpdCkKYGBgCgpPSywgc28gb3VyIGZpcnN0IG1vZGVsIGhhZCBhIG1lYW4gYHJtc2VgIHZhbHVlIG9mIDIuMTcuCkl0IGxvb2tzIGxpa2UgdGhlIHJhbmRvbSBmb3Jlc3QgbW9kZWwgaGFkICBhIG11Y2ggbG93ZXIgYHJtc2VgIHZhbHVlIG9mIDEuNzIuCgojIyMjIHsudGhpbmtfcXVlc3Rpb25fYmxvY2t9CjxiPjx1PiBRdWVzdGlvbiBPcHBvcnR1bml0eSA8L3U+PC9iPgoKRG8geW91IHJlY2FsbCBob3cgdGhlIFJNU0UgaXMgY2FsY3VsYXRlZD8KCiMjIyMKCioqKgoKPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHJldmVhbCB0aGUgYW5zd2VyLiA8L3N1bW1hcnk+CiQkUk1TRSA9IFxzcXJ0e1xmcmFje1xzdW1fe2k9MX1ee259eyhcaGF0e3lfdH0tIHlfdCl9XjJ9e259fSQkCjwvZGV0YWlscz4gCgpJZiB3ZSB0dW5lZCBvdXIgcmFuZG9tIGZvcmVzdCBtb2RlbCBiYXNlZCBvbiB0aGUgbnVtYmVyIG9mIHRyZWVzIG9yIHRoZSB2YWx1ZSBmb3IgYG10cnlgICh3aGljaCBpcyAiVGhlIG51bWJlciBvZiBwcmVkaWN0b3JzIHRoYXQgd2lsbCBiZSByYW5kb21seSBzYW1wbGVkIGF0IGVhY2ggc3BsaXQgd2hlbiBjcmVhdGluZyB0aGUgdHJlZSBtb2RlbHMiKSwgd2UgbWlnaHQgZ2V0IGEgbW9kZWwgd2l0aCBldmVuIGJldHRlciBwZXJmb3JtYW5jZS4KCkhvd2V2ZXIsIG91ciBjcm9zcyB2YWxpZGF0ZWQgbWVhbiBybXNlIHZhbHVlIG9mIDEuNzIgaXMgcXVpdGUgZ29vZCBiZWNhdXNlIG91ciByYW5nZSBvZiB0cnVlIG91dGNvbWUgdmFsdWVzIGlzIG11Y2ggbGFyZ2VyOiAoYHIgcm91bmQocmFuZ2UodGVzdF9wbSR2YWx1ZSksMylgKS4KCgojIyBNb2RlbCB0dW5pbmcKCltIeXBlcnBhcmFtZXRlcnNdKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vZGlmZmVyZW5jZS1iZXR3ZWVuLWEtcGFyYW1ldGVyLWFuZC1hLWh5cGVycGFyYW1ldGVyLykgYXJlIG9mdGVuIHRoaW5ncyB0aGF0IHdlIG5lZWQgdG8gc3BlY2lmeSBhYm91dCBhIG1vZGVsLiBGb3IgZXhhbXBsZSwgdGhlIG51bWJlciBvZiBwcmVkaWN0b3IgdmFyaWFibGVzIChvciBmZWF0dXJlcykgdGhhdCB3aWxsIGJlIHJhbmRvbWx5IHNhbXBsZWQgYXQgZWFjaCBzcGxpdCB3aGVuIGNyZWF0aW5nIHRoZSB0cmVlIG1vZGVscyBjYWxsZWQgYG10cnlgIGlzIGEgaHlwZXJwYXJhbWV0ZXIuIFRoZSBkZWZhdWx0IG51bWJlciBmb3IgcmVncmVzc2lvbiBhbmFseXNlcyBpcyB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgZGl2aWRlZCBieSAzLiBJbnN0ZWFkIG9mIGFyYml0cmFyaWx5IHNwZWNpZnlpbmcgdGhpcywgd2UgY2FuIHRyeSB0byBkZXRlcm1pbmUgdGhlIGJlc3Qgb3B0aW9uIGZvciBtb2RlbCBwZXJmb3JtYW5jZSBieSBhIHByb2Nlc3MgY2FsbGVkIHR1bmluZy4gCgoKTm93IGxldCdzIHRyeSBzb21lIHR1bmluZy4KCkxldCdzIHRha2UgYSBjbG9zZXIgbG9vayBhdCB0aGUgYG10cnlgIGFuZCBgbWluX25gIGh5cGVycGFyYW1ldHJzIGluIG91ciBSYW5kb20gRm9yZXN0IG1vZGVsLgoKV2UgYXJlbid0IGV4YWN0bHkgc3VyZSB3aGF0IHZhbHVlcyBvZiBgbXRyeWAgYW5kIGBtaW5fbmAgYWNoaWV2ZSBnb29kIGFjY3VyYWN5IHlldCBrZWVwIG91ciBtb2RlbCBnZW5lcmFsaXphYmxlIGZvciBvdGhlciBkYXRhLgoKVGhpcyBpcyB3aGVuIG91ciBjcm9zcyB2YWxpZGF0aW9uIG1ldGhvZHMgYmVjb21lIHJlYWxseSBoYW5keSBiZWNhdXNlIG5vdyB3ZSBjYW4gdGVzdCBvdXQgZGlmZmVyZW50IHZhbHVlcyBmb3IgZWFjaCBvZiB0aGVzZSBoeXBlcnBhcmFtZXRlcnMgdG8gYXNzZXNzIHdoYXQgdmFsdWVzIHNlZW0gdG8gd29yayBiZXN0IGZvciBtb2RlbCBwZXJmb3JtYW5jZSBvbiB0aGVzZSByZXNhbXBsZXMgb2Ygb3VyIHRyYWluaW5nIHNldCBkYXRhLgoKUHJldmlvdXNseSB3ZSBzcGVjaWZpZWQgb3VyIG1vZGVsIGxpa2Ugc286CmBgYHtyfQpSRl9QTV9tb2RlbCA8LSAKICBwYXJzbmlwOjpyYW5kX2ZvcmVzdChtdHJ5ID0gMTAsIG1pbl9uID0gMykgJT4lCiAgc2V0X2VuZ2luZSgicmFuZG9tRm9yZXN0IikgJT4lCiAgc2V0X21vZGUoInJlZ3Jlc3Npb24iKQoKUkZfUE1fbW9kZWwKYGBgCk5vdyBpbnN0ZWFkIG9mIHNwZWNpZnlpbmcgYSB2YWx1ZSBmb3IgdGhlIGBtdHJ5YCBhbmQgYG1pbl9uYCBhcmd1bWVudHMsIHdlIGNhbiB1c2UgdGhlIGB0dW5lKClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZSBsaWtlIHNvOiBgbXRyeSA9IHR1bmUoKWAuIFRoaXMgaW5kaWNhdGVzIHRoYXQgdGhlc2UgaHlwZXJwYXJhbWV0ZXJzIGFyZSB0byBiZSB0dW5lZC4gCgpgYGB7cn0KCnR1bmVfUkZfbW9kZWwgPC0gcmFuZF9mb3Jlc3QobXRyeSA9IHR1bmUoKSwgbWluX24gPSB0dW5lKCkpICU+JQogIHNldF9lbmdpbmUoInJhbmRvbUZvcmVzdCIpICU+JQogIHNldF9tb2RlKCJyZWdyZXNzaW9uIikKICAgIAoKdHVuZV9SRl9tb2RlbAoKYGBgCgoKQWdhaW4gd2Ugd2lsbCBhZGQgdGhpcyB0byBhIHdvcmtmbG93LCB0aGUgb25seSBkaWZmZXJlbmNlIGhlcmUgaXMgdGhhdCB3ZSBhcmUgdXNpbmcgYSBkaWZmZXJlbnQgbW9kZWwgc3BlY2lmaWNhdGlvbiB3aXRoIGB0dW5lX1JGX21vZGVsYCBpbnN0ZWFkIG9mIGBSRl9tb2RlbGA6CgpgYGB7cn0KClJGX3R1bmVfd2Zsb3cgPC0gd29ya2Zsb3dzOjp3b3JrZmxvdygpICU+JQogICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9yZWNpcGUoUkZfcmVjKSAlPiUKICAgICAgICAgICAgd29ya2Zsb3dzOjphZGRfbW9kZWwodHVuZV9SRl9tb2RlbCkKUkZfdHVuZV93ZmxvdwoKYGBgCgoKTm93IHdlIGNhbiB1c2UgdGhlIGB0dW5lX2dyaWQoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlIHRvIGV2YWx1YXRlIGRpZmZlcmVudCBjb21iaW5hdGlvbnMgb2YgdmFsdWVzIGZvciBgbXRyeWAgYW5kIGBtaW5fbmAgdXNpbmcgb3VyIGNyb3NzIHZhbGlkYXRpb24gc2FtcGxlcyBvZiBvdXIgdHJhaW5pbmcgc2V0IChgdmZvbGRfcG1gKSB0byBzZWUgd2hhdCBjb21iaW5hdGlvbiBvZiB2YWx1ZXMgcGVyZm9ybXMgYmVzdC4KClRvIHVzZSB0aGlzIGZ1bmN0aW9uIHdlIHdpbGwgc3BlY2lmeSB0aGUgd29ya2Zsb3cgdXNpbmcgdGhlIGBvYmplY3RgIGFyZ3VtZW50ICBhbmQgdGhlIHNhbXBsZXMgdG8gdXNlIHVzaW5nIHRoZSBgcmVzYW1wbGVzYCBhcmd1bWVudC4gVGhlIGBncmlkYCBhcmd1bWVudCBzcGVjaWZpZXMgaG93IG1hbnkgcG9zc2libGUgb3B0aW9ucyBmb3IgZWFjaCBhcmd1bWVudCBzaG91bGQgYmUgYXR0ZW1wdGVkLgoKQnkgZGVmYXVsdCAxMCBkaWZmZXJlbnQgdmFsdWVzIHdpbGwgYmUgYXR0ZW1wdGVkIGZvciBlYWNoIGh5cGVycGFyYW1ldGVyIHRoYXQgaXMgYmVpbmcgdHVuZWQuCgpXZSBjYW4gdXNlIHRoZSBgZG9QYXJhbGxlbGAgcGFja2FnZSB0byBhbGxvdyB1cyB0byBmaXQgYWxsIHRoZXNlIG1vZGVscyB0byBvdXIgY3Jvc3MgdmFsaWRhdGlvbiBzYW1wbGVzIGZhc3Rlci4gU28gaWYgeW91IHdlcmUgcGVyZm9ybWluZyB0aGlzIG9uIGEgY29tcHV0ZXIgd2l0aCBtdWx0aXBsZSBjb3JlcyBvciBwcm9jZXNzb3JzLCB0aGVuIGRpZmZlcmVudCBtb2RlbHMgd2l0aCBkaWZmZXJlbnQgaHlwZXJwYXJhbWV0ZXIgdmFsdWVzIGNhbiBiZSBmaXQgdG8gdGhlIGNyb3NzIHZhbGlkYXRpb24gc2FtcGxlcyBzaW11bHRhbmVvdXNseSBhY3Jvc3MgZGlmZmVyZW50IGNvcmVzIG9yIHByb2Nlc3NvcnMuIAoKWW91IGNhbiBzZWUgaG93IG1hbnkgY29yZXMgeW91IGhhdmUgYWNjZXNzIHRvIG9uIHlvdXIgc3lzdGVtIHVzaW5nIHRoZSBgZGV0ZWN0Q29yZXMoKWAgZnVuY3Rpb24gaW4gdGhlIGBwYXJhbGxlbGAgcGFja2FnZS4gCgpgYGB7cn0KcGFyYWxsZWw6OmRldGVjdENvcmVzKCkKYGBgCgpUaGUgYHJlZ2lzdGVyRG9QYXJhbGxlbCgpYCBmdW5jdGlvbiB3aWxsIHVzZSB0aGUgbnVtYmVyIGZvciBjb3JlcyBzcGVjaWZpZWQgdXNpbmcgdGhlIGBjb3Jlcz1gIGFyZ3VlbWVudCwgb3IgaXQgd2lsbCBhc3NpZ24gaXQgYXV0b21hdGljYWxseSB0byBvbmUtaGFsZiBvZiB0aGUgbnVtYmVyIG9mIGNvcmVzIGRldGVjdGVkIGJ5IHRoZSBgcGFyYWxsZWxgIHBhY2thZ2UuIAoKV2UgbmVlZCB0byB1c2UgYHNldC5zZWVkKClgIGhlcmUgYmVjYXVzZSB0aGUgdmFsdWVzIGNob3NlbiBmb3IgYG10cnlgIGFuZCBgbWluX25gIG1heSB2YXJ5IGlmIHdlIHByZWZvcm0gdGhpcyBldmFsdWF0aW9uIGFnYWluIGJlY2F1c2UgdGhleSBhcmUgY2hvc2VuIHNlbWktcmFuZG9tbHkgKG1lYW5pbmcgdGhhdCB0aGV5IGFyZSB3aXRoaW4gYSByYW5nZSBvZiByZWFzb25hYmxlIHZhbHVlcyBidXQgc3RpbGwgcmFuZG9tKS4KCk5vdGU6IHRoaXMgc3RlcCB3aWxsIHRha2Ugc29tZSB0aW1lLgoKYGBge3J9CmRvUGFyYWxsZWw6OnJlZ2lzdGVyRG9QYXJhbGxlbChjb3Jlcz0yKQpzZXQuc2VlZCgxMjMpCnR1bmVfUkZfcmVzdWx0cyA8LSB0dW5lX2dyaWQob2JqZWN0ID0gUkZfdHVuZV93ZmxvdywgcmVzYW1wbGVzID0gdmZvbGRfcG0sIGdyaWQgPSAyMCkKdHVuZV9SRl9yZXN1bHRzCmBgYAoKClNlZSBbdGhlIHR1bmUgZ2V0dGluZyBzdGFydGVkIGd1aWRlIF0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby90dW5lL2FydGljbGVzL2dldHRpbmdfc3RhcnRlZC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IGltcGxlbWVudGluZyB0aGlzIGluIGB0aWR5bW9kZWxzYC4KCklmIHlvdSB3YW50ZWQgbW9yZSBjb250cm9sIG92ZXIgdGhpcyBwcm9jZXNzIHlvdSBjb3VsZCBzcGVjaWZ5IGhvdyB0aGUgZGlmZmVyZW50IHBvc3NpYmxlIG9wdGlvbnMgZm9yIGBtdHJ5YCBhbmQgYG1pbl9uYCBpbiB0aGUgYHR1bmVfZ3JpZCgpYCBmdW5jdGlvbiB1c2luZyB0aGUgYGdyaWRfKigpYCBmdW5jdGlvbnMgb2YgdGhlIGBkaWFsc2AgcGFja2FnZSB0byBjcmVhdGUgYSBtb3JlIHNwZWNpZmljIGdyaWQuCgpCZSBkZWZhdWx0IHRoZSB2YWx1ZXMgZm9yIHRoZSBoeXBlcnBhcmFtZXRlcnMgYmVpbmcgdHVuZWQgYXJlIGNob3NlbiBzZW1pLXJhbmRvbWx5IChtZWFuaW5nIHRoYXQgdGhleSBhcmUgd2l0aGluIGEgcmFuZ2Ugb2YgcmVhc29uYWJsZSB2YWx1ZXMgYnV0IHN0aWxsIHJhbmRvbSkuLgoKCk5vdyB3ZSBjYW4gdXNlIHRoZSBgY29sbGVjdF9tZXRyaWNzKClgIGZ1bmN0aW9uIGFnYWluIHRvIHRha2UgYSBsb29rIGF0IHdoYXQgaGFwcGVuZWQgd2l0aCBvdXIgY3Jvc3MgdmFsaWRhdGlvbiB0ZXN0cy4gV2UgY2FuIHNlZSB0aGUgZGlmZmVyZW50IHZhbHVlcyBjaG9zZW4gZm9yIGBtdHJ5YCBhbmQgYG1pbl9uYCBhbmQgdGhlIG1lYW4gcm1zZSBhbmQgcnNxIHZhbHVlcyBhY3Jvc3MgdGhlIGNyb3NzIHZhbGlkYXRpb24gc2FtcGxlcy4KCmBgYHtyfQp0dW5lX1JGX3Jlc3VsdHMlPiUKICBjb2xsZWN0X21ldHJpY3MoKQpgYGAKCldlIGNhbiBub3cgdXNlIHRoZSBgc2hvd19iZXN0KClgIGZ1bmN0aW9uIGFzIGl0IHdhcyB0cnVseSBpbnRlbmRlZCwgdG8gc2VlIHdoYXQgdmFsdWVzIGZvciBgbWluX25gIGFuZCBgbXRyeWAgcmVzdWx0ZWQgaW4gdGhlIGJlc3QgcGVyZm9ybWFuY2UuCgpgYGB7cn0Kc2hvd19iZXN0KHR1bmVfUkZfcmVzdWx0cywgbWV0cmljID0gInJtc2UiLCBuID0xKQpgYGAKVGhlcmUgd2UgaGF2ZSBpdC4uLiBsb29rcyBsaWtlIGFuIGBtdHJ5YCBvZiAxNyBhbmQgYG1pbl9uYCBvZiA0IGhhZCB0aGUgYmVzdCBgcm1zZWAgdmFsdWUuIFlvdSBjYW4gdmVyaWZ5IHRoaXMgaW4gdGhlIGFib3ZlIG91dHB1dCwgYnV0IGl0IGlzIGVhc2llciB0byBqdXN0IHB1bGwgdGhpcyByb3cgb3V0IHVzaW5nIHRoaXMgZnVuY3Rpb24uIFdlIGNhbiBzZWUgdGhhdCB0aGUgbWVhbiBgcm1zZWAgdmFsdWUgYWNyb3NzIHRoZSBjcm9zcyB2YWxpZGF0aW9uIHNldHMgd2FzIDEuNzEyLiBCZWZvcmUgdHVuaW5nIGl0IHdhcyAxLjcyNSAgd2l0aCBhIHNpbWlsYXIgYHN0ZF9lcnJgIHNvIHRoZSBwZXJmb3JtYW5jZSB3YXMgdmVyeSBzbGlnaHRseSBpbXByb3ZlZC4KCgojIyBGaW5hbCBtb2RlbCBwZXJmb3JtYW5jZSBldmFsdWF0aW9uCgpOb3cgdGhhdCB3ZSBoYXZlIGRlY2lkZWQgdGhhdCB3ZSBoYXZlIHJlYXNvbmFibGUgcGVyZm9ybWFuY2Ugd2l0aCBvdXIgdHJhaW5pbmcgZGF0YSwgd2UgY2FuIHN0b3AgYnVpbGRpbmcgb3VyIG1vZGVsIGFuZCBldmFsdWF0ZSBwZXJmb3JtYW5jZSB3aXRoIG91ciB0ZXN0aW5nIGRhdGEuIAoKSGVyZSwgd2Ugd2lsbCB1c2UgdGhlIHJhbmRvbSBmb3Jlc3QgbW9kZWwgdGhhdCB3ZSBidWlsdCB0byBwcmVkaWN0IHZhbHVlcyBmb3IgdGhlIG1vbml0b3JzIGluIHRoZSB0ZXN0aW5nIGRhdGEgYW5kIHdlIHdpbGwgdXNlIHRoZSB2YWx1ZXMgZm9yIGBtdHJ5YCBhbmQgYG1pbl9uYCB0aGF0IHdlIGp1c3QgZGV0ZXJtaW5lZCBiYXNlZCBvbiBvdXIgdHVuaW5nIGFuYWx5c2lzIHRvIGFjaGlldmUgdGhlIGJlc3QgcGVyZm9ybWFuY2UuCgpTbywgZmlyc3Qgd2UgbmVlZCB0byBzcGVjaWZ5IHRoZXNlIHZhbHVlcyBpbiBhIHdvcmtmbG93LiBXZSBjYW4gdXNlIHRoZSBgc2VsZWN0X2Jlc3QoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlIHRvIGdyYWIgdGhlIHZhbHVlcyB0aGF0IHdlcmUgZGV0ZXJtaW5lZCB0byBiZSBiZXN0IGZvciBgbXRyeWAgYW5kIGBtaW5fbmAuCgoKCmBgYHtyfQoKdHVuZWRfUkZfdmFsdWVzPC0gc2VsZWN0X2Jlc3QodHVuZV9SRl9yZXN1bHRzLCAicm1zZSIpCnR1bmVkX1JGX3ZhbHVlcwpgYGAKCk5vdyB3ZSBjYW4gZmluYWxpemUgdGhlIG1vZGVsL3dvcmtmbG93IHRoYXQgd2Ugd2UgdXNlZCBmb3IgdHVuaW5nIHdpdGggdGhlc2UgdmFsdWVzLgoKCmBgYHtyfQpSRl90dW5lZF93ZmxvdyA8LVJGX3R1bmVfd2Zsb3cgJT4lCiAgdHVuZTo6ZmluYWxpemVfd29ya2Zsb3codHVuZWRfUkZfdmFsdWVzKQpgYGAKCgpXaXRoIHRoZSBgd29ya2Zsb3dzYCBwYWNrYWdlLCB3ZSBjYW4gdXNlIHRoZSBzcGxpdHRpbmcgaW5mb3JtYXRpb24gZm9yIG91ciBvcmlnaW5hbCBkYXRhIGBwbV9zcGxpdGAgdG8gZml0IHRoZSBmaW5hbCBtb2RlbCBvbiB0aGUgZnVsbCB0cmFpbmluZyBzZXQgYW5kIGFsc28gb24gdGhlIHRlc3RpbmcgZGF0YSB1c2luZyB0aGUgYGxhc3RfZml0KClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZS4gTm8gcHJlLXByb2Nlc3Npbmcgc3RlcHMgYXJlIHJlcXVpcmVkLgoKVGhlIHJlc3VsdHMgd2lsbCBzaG93IHRoZSBwZXJmb3JtYW5jZSB1c2luZyB0aGUgdGVzdGluZyBkYXRhLgoKCmBgYHtyfQpvdmVyYWxsZml0IDwtdHVuZTo6bGFzdF9maXQoUkZfdHVuZWRfd2Zsb3csIHBtX3NwbGl0KQogIyBvcgpvdmVyYWxsZml0IDwtUkZfd2Zsb3cgJT4lCiAgdHVuZTo6bGFzdF9maXQocG1fc3BsaXQpCmBgYAoKVGhlIGBvdmVyYWxsZml0YCBvdXRwdXQgaGFzIGEgbG90IG9mIHJlYWxseSB1c2VmdWwgaW5mb3JtYXRpb24gYWJvdXQgdGhlIG1vZGVsLCB0aGUgdGVzdGluZyBhbmQgdHJhaW5pbmcgZGF0YSBzcGxpdCwgYW5kIHRoZSBwcmVkaWN0aW9ucyBmb3IgdGhlIHRlc3RpbmcgZGF0YS4KClRvIHNlZSB0aGUgcGVyZm9ybWFuY2Ugb24gdGhlIHRlc3QgZGF0YSB3ZSBjYW4gdXNlIHRoZSBgY29sbGVjdF9tZXRyaWNzKClgIGZ1bmN0aW9uIGxpa2Ugd2UgZGlkIGJlZm9yZS4KYGBge3J9CiAgY29sbGVjdF9tZXRyaWNzKG92ZXJhbGxmaXQpCiAKYGBgCgpBd2Vzb21lISBXZSBjYW4gc2VlIHRoYXQgb3VyIHJtc2Ugb2YgMS40NCBpcyBxdWl0ZSBzaW1pbGFyIHdpdGggb3VyIHRlc3RpbmcgZGF0YSBjcm9zcyB2YWxpZGF0aW9uIHNldHMuIFdlIGFjaGlldmVkIHF1aXRlIGdvb2QgcGVyZm9ybWFuY2UsIHdoaWNoIHN1Z2dlc3RzIHRoYXQgd2Ugd291bGQgY291bGQgcHJlZGljdCBvdGhlciBsb2NhdGlvbnMgd2l0aCBtb3JlIHNwYXJzZSBtb25pdG9yaW5nIGJhc2VkIG9uIG91ciBwcmVkaWN0b3JzIHdpdGggcmVhc29uYWJsZSBhY2N1cmFjeS4KCk5vdyBpZiB5b3Ugd2FudGVkIHRvIHRha2UgYSBsb29rIGF0IHRoZSBwcmVkaWN0ZWQgdmFsdWVzIGZvciB0aGUgdGVzdCBzZXQgKHRoZSAyOTIgcm93cyB3aXRoIHByZWRpY3Rpb25zIG91dCBvZiB0aGUgODc2IG9yaWdpbmFsIG1vbml0b3IgdmFsdWVzKSB5b3UgY2FuIHVzZSB0aGUgIGBjb2xsZWN0X3ByZWRpY3Rpb25zKClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZSgpYCBwYWNrYWdlOgoKYGBge3J9CnRlc3RfcHJlZGljdGlvbnMgPC1jb2xsZWN0X3ByZWRpY3Rpb25zKG92ZXJhbGxmaXQpCmBgYAoKYGBge3IsIGV2YWwgPSBGQUxTRX0KdGVzdF9wcmVkaWN0aW9ucwpgYGAKCiMjIyMgey5zY3JvbGxhYmxlIH0KYGBge3IsIGVjaG8gPUZBTFNFfQp0ZXN0X3ByZWRpY3Rpb25zICU+JQogIHByaW50KG4gPSAxZTMpCmBgYAoKIyMjIwoKTmljZSEKCiMgKipEYXRhIFZpc3VhbGl6YXRpb24qKgoqKioKCk91ciBtYWluIHF1ZXN0aW9uIGZvciB0aGlzIGNhc2Ugc3R1ZHkgd2FzOiAgCgo+IENhbiB3ZSBwcmVkaWN0IGFubnVhbCBhdmVyYWdlIGFpciBwb2xsdXRpb24gY29uY2VudHJhdGlvbnMgYXQgdGhlIGdyYW51bGFyaXR5IG9mIHppcCBjb2RlIHJlZ2lvbmFsIGxldmVscyB1c2luZyBwcmVkaWN0b3JzIHN1Y2ggYXMgZGF0YSBhYm91dCBwb3B1bGF0aW9uIGRlbnNpdHksIHVyYmFuaXphdGlvbiwgcm9hZCBkZW5zaXR5LCBhcyB3ZWxsIGFzLCBzYXRlbGxpdGUgcG9sbHV0aW9uIGRhdGEgYW5kIGNoZW1pY2FsIG1vZGVsaW5nIGRhdGE/CgpUaHVzIGZhciwgd2UgaGF2ZSBidWlsZCBhIG1hY2hpbmUgbGVhcm5pbmcgKE1MKSBtb2RlbCB0byBwcmVkaWN0IGZpbmUgcGFydGljdWxhdGUgbWF0dGVyIGFpciBwb2xsdXRpb24gbGV2ZWxzIGJhc2VkIG9uIG91ciBwcmVkaWN0b3IgdmFyaWFibGVzIChvciBmZWF0dXJlcykuCgpOb3csIGxldCdzIG1ha2UgYSBwbG90IG9mIG91ciBwcmVkaWN0ZWQgb3V0Y29tZSB2YWx1ZXMgKCRcaGF0e1l9JCkgYW5kIGFjdHVhbCBvdXRjb21lIHZhbHVlcyAkWSQgd2Ugb2JzZXJ2ZWQuIAoKRmlyc3QsIGxldCdzIHN0YXJ0IGJ5IG1ha2luZyBhIHBsb3Qgb2Ygb3VyIG1vbml0b3JzLiAKVG8gZG8gdGhpcywgd2Ugd2lsbCB1c2UgdGhlIGZvbGxvd2luZyBwYWNrYWdlcyB0byBjcmVhdGUgYSBtYXAgb2YgdGhlIFVTOgoKMS4gYHNmYCAtIHRoZSBzaW1wbGUgZmVhdHVyZXMgcGFja2FnZSBoZWxwcyB0byBjb252ZXJ0IGdlb2dyYXBoaWNhbCBjb29yZGluYXRlcyBpbnRvIGBnZW9tZXRyeWAgdmFyaWFibGVzIHdoaWNoIGFyZSB1c2VmdWwgZm9yIG1ha2luZyAyRCBwbG90cwoyLiBgbWFwc2AgLSB0aGlzIHBhY2thZ2UgY29udGFpbnMgZ2VvZ3JhcGhpY2FsIG91dGxpbmVzIGFuZCBwbG90dGluZyBmdW5jdGlvbnMgdG8gY3JlYXRlIHBsb3RzIHdpdGggbWFwcyAKMy4gYHJuYXR1cmFsZWFydGhgLSB0aGlzIGFsbG93cyBmb3IgZWFzeSBpbnRlcmFjdGlvbiB3aXRoIG1hcCBkYXRhIGZyb20gW05hdHVyYWwgRWFydGhdKGh0dHA6Ly93d3cubmF0dXJhbGVhcnRoZGF0YS5jb20vKSB3aGljaCBpcyBhIHB1YmxpYyBkb21haW4gbWFwIGRhdGFzZXQKNC4gYHJnZW9zYCAtIHRoaXMgcGFja2FnZSBpbnRlcmZhY2VzIHdpdGggdGhlIEdlb21ldHJ5IEVuZ2luZS1PcGVuIFNvdXJjZSAoYEdFT1NgKSB3aGljaCBpcyBhbHNvIGhlbHBmdWwgZm9yIGNvb3JkaW5hdGUgY29udmVyc2lvbgoKV2Ugd2lsbCBzdGFydCB3aXRoIGdldHRpbmcgYW4gb3V0bGluZSBvZiB0aGUgVVMgd2l0aCB0aGUgYG5lX2NvdW50cmllcygpYCBmdW5jdGlvbiBvZiB0aGUgYHJuYXR1cmFsZWFydGhgIHBhY2thZ2Ugd2hpY2ggd2lsbCByZXR1cm4gcG9seWdvbnMgb2YgdGhlIGNvdW50cmllcyBpbiB0aGUgW05hdHVyYWwgRWFydGhdKGh0dHA6Ly93d3cubmF0dXJhbGVhcnRoZGF0YS5jb20vKSBkYXRhc2V0LgoKYGBge3J9Cgp3b3JsZCA8LSBuZV9jb3VudHJpZXMoc2NhbGUgPSAibWVkaXVtIiwgcmV0dXJuY2xhc3MgPSAic2YiKQpnbGltcHNlKHdvcmxkKQoKYGBgCgoKSGVyZSB5b3UgY2FuIHNlZSB0aGUgZGF0YSBhYm91dCB0aGUgY291bnRyaWVzIGluIHRoZSB3b3JsZC4gTm90aWNlIHRoZSBgZ2VvbWV0cnlgIHZhcmlhYmxlLiBUaGlzIGlzIHVzZWQgdG8gY3JlYXRlIHRoZSBvdXRsaW5lcyB0aGF0IHdlIHdhbnQuIAoKTm93IHdlIGNhbiB1c2UgdGhlIGBnZW9tX3NmKClgIGZ1bmN0aW9uIG9mIHRoZSBgZ2dwbG90MmAgcGFja2FnZSB0byBjcmVhdGUgYSB2aXN1YWwgb2Ygc2ltcGxlIGZlYXR1cmUgKHRoZSBnZW9tZXRyeSBjb29yZGluYXRlcyBmb3VuZCBpbiB0aGUgYGdlb21ldHJ5YCB2YXJpYWJsZSkuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSB3b3JsZCkgKwogICAgZ2VvbV9zZigpIAoKYGBgCgpTbyBub3cgd2UgY2FuIHNlZSB0aGF0IHdlIGhhdmUgb3V0bGluZXMgb2YgYWxsIHRoZSBjb3VudHJpZXMgaW4gdGhlIHdvcmxkLgoKV2Ugd2FudCB0byBsaW1pdCB0aGlzIGp1c3QgdG8gdGhlIGNvb3JkaW5hdGVzIGZvciB0aGUgVVMuIFdlIHdpbGwgZG8gdGhpcyBiYXNlZCBvbiB0aGUgY29vcmRpbmF0ZXMgd2UgZm91bmQgb24gV2lraXBlZGlhLiBBY2NvcmRpbmcgdG8gdGhpcyBbbGlua10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGlzdF9vZl9leHRyZW1lX3BvaW50c19vZl90aGVfVW5pdGVkX1N0YXRlcyNXZXN0ZXJubW9zdCl7dGFyZ2V0PSJfYmxhbmsifSwgdGhlc2UgYXJlIHRoZSBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIGJvdW5kcyBvZiB0aGUgY29udGluZW50YWwgVVM6CgotIHRvcCA9IDQ5LjM0NTc4NjggIyBub3J0aCBsYXQKLSBsZWZ0ID0gLTEyNC43ODQ0MDc5ICMgd2VzdCBsb25nCi0gcmlnaHQgPSAtNjYuOTUxMzgxMiAjIGVhc3QgbG9uZwotIGJvdHRvbSA9ICAyNC43NDMzMTk1ICMgc291dGggbGF0CgpgYGB7cn0KCmdncGxvdChkYXRhID0gd29ybGQpICsKICAgIGdlb21fc2YoKSArCiAgICBjb29yZF9zZih4bGltID0gYygtMTI1LCAtNjYpLCB5bGltID0gYygyNC41LCA1MCksIAogICAgICAgICAgICAgZXhwYW5kID0gRkFMU0UpCmBgYApOb3cgd2UganVzdCBoYXZlIGEgcGxvdCB0aGF0IGlzIG1vc3RseSBsaW1pdGVkIHRvIHRoZSBvdXRsaW5lIG9mIHRoZSBVUy4KCk5vdyB3ZSB3aWxsIHVzZSB0aGUgYGdlb21fcG9pbnQoKWAgZnVuY3Rpb24gb2YgdGhlIGBnZ3Bsb3RgIHBhY2thZ2UgdG8gYWRkIHNjYXR0ZXIgcGxvdCBvbiB0b3Agb2YgdGhlIG1hcC4gV2Ugd2FudCB0byBzaG93IHdoZXJlIHRoZSBtb25pdG9ycyBhcmUgbG9jYXRlZCBiYXNlZCBvbiB0aGUgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSB2YWx1ZXMgaW4gdGhlIGRhdGEuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSB3b3JsZCkgKwogICAgZ2VvbV9zZigpICsKICAgIGNvb3JkX3NmKHhsaW0gPSBjKC0xMjUsIC02NiksIHlsaW0gPSBjKDI0LjUsIDUwKSwgCiAgICAgICAgICAgICBleHBhbmQgPSBGQUxTRSkrCiAgICBnZW9tX3BvaW50KGRhdGEgPSBwbSwgYWVzKHggPSBsb24sIHkgPSBsYXQpLCBzaXplID0gMiwgCiAgICAgICAgICAgICAgIHNoYXBlID0gMjMsIGZpbGwgPSAiZGFya3JlZCIpCgpgYGAKTmljZSEKCk5vdyBsZXQncyBhZGQgY291bnR5IGxpbmVzLgoKQ291bnR5IGdyYXBoaWNhbCBkYXRhIGlzIGF2YWlsYWJsZSBmcm9tIHRoZSBgbWFwc2AgcGFja2FnZS4gClRoZSBgc2ZgIHBhY2thZ2Ugd2hpY2ggYWdhaW4gaXMgc2hvcnQgZm9yIHNpbXBsZSBmZWF0dXJlcyBjcmVhdGVzIGEgZGF0YSBmcmFtZSBhYm91dCB0aGlzIGdyYXBoaWNhbCBkYXRhIHNvIHRoYXQgd2UgY2FuIHdvcmsgd2l0aCBpdC4KCmBgYHtyfQpjb3VudGllcyA8LSAKICBzZjo6c3RfYXNfc2YobWFwczo6bWFwKCJjb3VudHkiLCBwbG90ID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IFRSVUUpKQoKY291bnRpZXMKYGBgCgpOb3cgd2Ugd2lsbCB1c2UgdGhpcyBkYXRhIHdpdGhpbiB0aGUgYGdlb21fc2YoKWAgZnVuY3Rpb24gdG8gYWRkIHRoaXMgdG8gb3VyIHBsb3QuICBXZSB3aWxsIGFsc28gYWRkIGEgdGl0bGUgdXNpbmcgdGhlIGBnZ3RpdGxlKClgIGZ1bmN0aW9uLCBhcyB3ZWxsIGFzIHJlbW92ZSBheGlzIHRpY2tzIGFuZCB0aXRsZXMgdXNpbmcgdGhlIGB0aGVtZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGdncGxvdDJgIHBhY2thZ2UuCgpgYGB7cn0KbW9uaXRvcnMgPC0gZ2dwbG90KGRhdGEgPSB3b3JsZCkgKwogICAgZ2VvbV9zZihkYXRhID0gY291bnRpZXMsIGZpbGwgPSBOQSwgY29sb3IgPSBncmF5KC41KSkrCiAgICAgIGNvb3JkX3NmKHhsaW0gPSBjKC0xMjUsIC02NiksIHlsaW0gPSBjKDI0LjUsIDUwKSwgCiAgICAgICAgICAgICBleHBhbmQgPSBGQUxTRSkgKwogICAgZ2VvbV9wb2ludChkYXRhID0gcG0sIGFlcyh4ID0gbG9uLCB5ID0gbGF0KSwgc2l6ZSA9IDIsIAogICAgICAgICAgICAgICBzaGFwZSA9IDIzLCBmaWxsID0gImRhcmtyZWQiKSArCiAgICBnZ3RpdGxlKCJNb25pdG9yIExvY2F0aW9ucyIpICsKICAgIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkKCm1vbml0b3JzCmBgYAoKR3JlYXQhCgpOb3csIGxldCdzIGFkZCBhIGZpbGwgYXQgdGhlIGNvdW50eS1sZXZlbCBmb3IgdGhlIHRydWUgbW9uaXRvciB2YWx1ZXMgb2YgYWlyIHBvbGx1dGlvbi4KCkZpcnN0LCB3ZSBuZWVkIHRvIGdldCB0aGUgY291bnR5IG1hcCBkYXRhIHRoYXQgd2UganVzdCBnb3QgYW5kIG91ciBhaXIgcG9sbHV0aW9uIGRhdGEgdG8gaGF2ZSBzaW1pbGFybHkgZm9ybWF0dGVkIGNvdW50eSBuYW1lcyBzbyB0aGF0IHdlIGNhbiBjb21iaW5lIHRoZSBkYXRhc2V0cyB0b2dldGhlci4KCldlIGNhbiBzZWUgdGhhdCBpbiB0aGUgYGNvdW50eWAgZGF0YSB0aGUgY291bnRpZXMgYXJlIGxpc3RlZCBhZnRlciB0aGUgc3RhdGUgbmFtZSBhbmQgYSBjb21tYS4gSW4gYWRkaXRpb24gdGhleSBhcmUgYWxsIGxvd2VyIGNhc2UuCgoKYGBge3J9CmhlYWQoY291bnRpZXMpCmBgYAoKSW4gY29udHJhc3QsIG91ciBhaXIgcG9sbHV0aW9uIGBwbWAgZGF0YSBzaG93cyBjb3VudGllcyBhcyB0aXRsZXMgd2l0aCB0aGUgZmlyc3QgbGV0dGVyIGFzIHVwcGVyIGNhc2UuIAoKYGBge3J9CmRwbHlyOjpwdWxsKHBtLCBjb3VudHkpICU+JQogIGhlYWQoKQpgYGAKCldlIGNhbiB1c2UgdGhlIGBzZXBhcmF0ZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHRpZHlyYCBwYWNrYWdlIHRvIHNlcGFyYXRlIHRoZSBgSURgIHZhcmlhYmxlIG9mIG91ciBgY291bnRpZXNgIGRhdGEgaW50byB0d28gYHZhcmlhYmxlc2AgYmFzZWQgb24gdGhlIGNvbW1hIGFzIGEgc2VwYXJhdG9yLgoKYGBge3J9CmNvdW50aWVzICU8PiUgCiAgdGlkeXI6OnNlcGFyYXRlKElELCBpbnRvID0gYygic3RhdGUiLCAiY291bnR5IiksIHNlcCA9ICIsIikKCmhlYWQoY291bnRpZXMpCmBgYApOb3cgd2UganVzdCBuZWVkIHRvIG1ha2UgdGhlc2UgbmFtZXMgaW4gdGhlIG5ldyBgY291bnR5YCB2YXJpYWJsZSBvZiB0aGUgYGNvdW50aWVzYCBkYXRhIHRvIGJlIGluIHRpdGxlIGZvcm1hdC4gV2UgY2FuIHVzZSB0aGUgYHN0cl90b190aXRsZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHN0cmluZ3JgIHBhY2thZ2UgdG8gZG8gdGhpcy4gCmBgYHtyfQpjb3VudGllc1tbImNvdW50eSJdXSA8LSBzdHJpbmdyOjpzdHJfdG9fdGl0bGUoY291bnRpZXNbWyJjb3VudHkiXV0pCmBgYAoKR3JlYXQhIE5vdyB0aGUgY291bnR5IGluZm9ybWF0aW9uIGlzIHRoZSBzYW1lIGZvciB0aGUgYGNvdW50aWVzYCBhbmQgYHBtYCBkYXRhLgoKV2UgY2FuIHVzZSB0aGUgYGlubmVyX2pvaW4oKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSB0byBqb2luIHRoZSBkYXRhc2V0cyB0b2dldGhlciBiYXNlZCBvbiB0aGUgYGNvdW50eWAgdmFyaWFibGVzIGluIGVhY2guIFRoaXMgZnVuY3Rpb24gd2lsbCBrZWVwIGFsbCByb3dzIHRoYXQgYXJlIGluIGJvdGggZGF0YXNldHMuCgpgYGB7cn0KbWFwX2RhdGEgPC1kcGx5cjo6aW5uZXJfam9pbihjb3VudGllcywgcG0sIGJ5ID0gImNvdW50eSIpCgpnbGltcHNlKG1hcF9kYXRhKQoKYGBgCk5pY2UhIHdlIGNhbiBzZWUgdGhhdCB3ZSBoYXZlIGFkZCBhIGBnZW9tYCB2YXJpYWJsZSB0byB0aGUgYHBtYCBkYXRhLgoKTm93IHdlIGNhbiB1c2UgdGhpcyB0byBjb2xvciB0aGUgY291bnRpZXMgaW4gb3VyIHBsb3QgYmFzZWQgb24gdGhlIGB2YWx1ZWAgdmFyaWFibGUgb2Ygb3VyIGBwbWAgZGF0YSwgd2hpY2ggeW91IG1heSByZWNhbGwgaXMgdGhlIGFjdHVhbCBtb25pdG9yIGRhdGEgZm9yIGZpbmUgcGFydGljdWxhdGUgYWlyIHBvbGx1dGlvbiBhdCBlYWNoIG1vbml0b3IuIAoKV0UgY2FuIGRvIHNvIHVzaW5nIHRoZSBgc2NhbGVfZmlsbF9ncmFkaWVudG4oKWAgZnVuY3Rpb24gb2YgdGhlIGBnZ3Bsb3QyYCBwYWNrYWdlIHdoaWNoIGNyZWF0ZXMgY29sb3IgZ3JhZGllbnQgYmFzZWQgb24gYSB2YXJpYWJsZS4gSW4gdGhpcyBjYXNlIGl0IGlzIHRoZSB2YXJpYWJsZSB0aGF0IHdhcyBzcGVjaWZpZWQgYXMgdGhlIGBmaWxsYCBpbiB0aGUgYGFlc2AgZnVuY3Rpb24gb2YgdGhlIGBnZW9tX3NmKClgIGZ1bmN0aW9uLiBXZSBzcGVjaWZpZWQgdGhhdCBpdCB3b3VsZCBiZSB0aGUgYHZhbHVlYCB2YXJpYWJsZSBvZiB0aGUgYHBtYCBkYXRhLgoKVGhpcyBgc2NhbGVfZmlsbF9ncmFkaWVudG4oKWAgZnVuY3Rpb24gIGFsc28gYWxsb3dzIHlvdSB0byBzcGVjaWZ5IHRoZSBjb2xvcnMsIHdoYXQgdG8gZG8gYWJvdXQgTkEgdmFsdWVzIChzaG91bGQgdGhleSBiZSBhIHNwZWNpZmljIGNvbG9yIG9yIHRyYW5zcGFyZW50KSBhbmQgdGhlIGJyZWFrcywgbGltaXRzLCBsYWJlbHMgYW5kIG5hbWUvdGl0bGUgb24gdGhlIGxlZ2VuZCBmb3IgdGhlIGNvbG9yIGdyYWRpZW50LiAKCmBgYHtyfQoKdHJ1dGggPC1nZ3Bsb3QoZGF0YSA9IHdvcmxkKSArCiAgY29vcmRfc2YoeGxpbSA9IGMoLTEyNSwgLTY2KSwgeWxpbSA9IGMoMjQuNSwgNTApLCBleHBhbmQgPSBGQUxTRSkrCiAgICBnZW9tX3NmKGRhdGEgPSBtYXBfZGF0YSwgYWVzKGZpbGwgPSB2YWx1ZSkpICsKICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPXRvcG8uY29sb3JzKDcpLCBuYS52YWx1ZSA9ICJ0cmFuc3BhcmVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcz1jKDAsMTAsMjApLGxhYmVscz1jKDAsMTAsMjApLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW1pdHM9YygwLDIzLjUpLCBuYW1lID0gIlBNIHVnL20zIikgKwogIGdndGl0bGUoIlRydWUgUE0gMi41IGxldmVscyIpICsKICAgIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkKCnRydXRoCgpgYGAKTmljZSEKCk5vdyBsZXQncyBkbyB0aGUgc2FtZSB3aXRoIG91ciBwcmVkaWN0ZWQgb3V0Y29tZSB2YWx1ZXMuCgpMZXQncyBncmFiIGJvdGggdGhlIHRlc3RpbmcgYW5kIHRyYWluaW5nIHByZWRpY3RlZCBvdXRjb21lIHZhbHVlcyBzbyB0aGF0IHdlIGhhdmUgYXMgbXVjaCBkYXRhIGFzIHBvc3NpYmxlLiAKCkZpcnN0IHdlIG5lZWQgdG8gZml0IG91ciB0cmFpbmluZyBkYXRhIHdpdGggb3VyIGZpbmFsIG1vZGVsIHRvIGJlIGFibGUgdG8gZ2V0IHRoZSBwcmVkaWN0aW9ucyBmb3IgdGhlIG1vbml0b3JzIGluY2x1ZGVkIGluIHRoZSB0cmFpbmluZyBzZXQuIFdlIGRpZCB0aGlzIHVzaW5nIHRoZSBgbGFzdF9maXQoKWAgZnVuY3Rpb24sIGJ1dCB0aGUgb3V0cHV0IG9mIHRoaXMgbWFrZXMgaXQgZGlmZmljdWx0IHRvIGdyYWIgdGhlIHByZWRpY3RlZCB2YWx1ZXMgZm9yIHRoZSB0cmFpbmluZyBkYXRhLCBhbmQgaXQgaXMgYWxzbyBkaWZmaWN1bHQgdG8gZ2V0IHRoZSBpZCB2YXJpYWJsZXMgZm9yIHRoZSB0ZXN0aW5nIGRhdGEuIAoKClRodXMgd2Ugd2lsbCB1c2UgdGhlIHBhcnNuaXAgYGZpdCgpYCBhbmQgYHByZWRpY3QoKWAgZnVuY3Rpb25zIG9mIHRoZSBgcGFyc25pcGAgcGFja2FnZSB0byBkbyB0aGlzIGxpa2Ugc286CgojIyMjIHsudGhpbmtfcXVlc3Rpb25fYmxvY2t9CjxiPjx1PiBRdWVzdGlvbiBPcHBvcnR1bml0eSA8L3U+PC9iPgoKV2h5IGRvIHdlIG5vdCBuZWVkIHByZS1wcm9jZXNzZWQgZGF0YT8KCiMjIyMKCioqKgoKPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHJldmVhbCB0aGUgYW5zd2VyLiA8L3N1bW1hcnk+CgpTaW5jZSB3ZSBhcmUgdXNpbmcgYSB3b3JrZmxvdywgdGhlIGRhdGEgd2lsbCBiZSBwcmUtcHJvY2Vzc2VkIHdoZW4gaXQgaXMgZml0IGFzIHdlbGwuCgo8L2RldGFpbHM+CioqKgoKCmBgYHtyfQoKUkZfZmluYWxfdHJhaW5fZml0IDwtIHBhcnNuaXA6OmZpdChSRl90dW5lZF93ZmxvdywgZGF0YSA9IHRyYWluX3BtKQpSRl9maW5hbF90ZXN0X2ZpdCA8LSBwYXJzbmlwOjpmaXQoUkZfdHVuZWRfd2Zsb3csIGRhdGEgPSB0ZXN0X3BtKQoKCnZhbHVlc19wcmVkX3RyYWluIDwtIAogIHByZWRpY3QoUkZfZmluYWxfdHJhaW5fZml0LCB0cmFpbl9wbSkgJT4lIAogIGJpbmRfY29scyh0cmFpbl9wbSAlPiUgc2VsZWN0KHZhbHVlLCBmaXBzLCBjb3VudHksIGlkKSkgCgp2YWx1ZXNfcHJlZF90cmFpbgoKdmFsdWVzX3ByZWRfdGVzdCA8LSAKICBwcmVkaWN0KFJGX2ZpbmFsX3Rlc3RfZml0LCB0ZXN0X3BtKSAlPiUgCiAgYmluZF9jb2xzKHRlc3RfcG0gJT4lIHNlbGVjdCh2YWx1ZSwgZmlwcywgY291bnR5LCBpZCkpIAoKdmFsdWVzX3ByZWRfdGVzdApgYGAKCk5vdyB3ZSBjYW4gY29tYmluZSB0aGlzIGRhdGEgZm9yIHRoZSBwcmVkaWN0aW9ucyBmb3IgYWxsIG1vbml0b3JzIHVzaW5nIHRoZSBgYmluZF9yb3dzKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UsIHdoaWNoIHdpbGwgZXNzZW50aWFsbHkgYXBwZW5kIHRoZSBzZWNvbmQgZGF0YXNldCB0byB0aGUgZmlyc3QuCgpgYGB7cn0KYWxsX3ByZWQgPC0gYmluZF9yb3dzKHZhbHVlc19wcmVkX3Rlc3QsIHZhbHVlc19wcmVkX3RyYWluKQoKYWxsX3ByZWQKYGBgCgpHcmVhdCEgYXMgd2UgY2FuIHNlZSB0aGVyZSBhcmUgODc2IHZhbHVlcyBsaWtlIHdlIHdvdWxkIGV4cGVjdCBmb3IgYWxsIG9mIHRoZSBtb25pdG9ycy4gV2UgY2FuIHVzZSB0aGUgYGNvdW50eWAgdmFyaWFibGUgdG8gY29tYmluZSB0aGlzIHdpdGggdGhlIGBjb3VudGllc2AgZGF0YSBsaWtlIHdlIGRpZCB3aXRoIHRoZSBgcG1gIGRhdGEgcHJldmlvdXNseSBzbyB0aGF0IHdlIGNhbiB1c2UgdGhlIGB2YWx1ZWAgdmFyaWFibGUgYXMgYSBjb2xvciBzY2hlbWUgZm9yIG91ciBtYXAuCgoKYGBge3J9Cm1hcF9kYXRhIDwtIGlubmVyX2pvaW4oY291bnRpZXMsIGFsbF9wcmVkLCBieSA9ICJjb3VudHkiKQoKcHJlZCA8LSBnZ3Bsb3QoZGF0YSA9IHdvcmxkKSArCiAgICAgICAgICBjb29yZF9zZih4bGltID0gYygtMTI1LCAtNjYpLCB5bGltID0gYygyNC41LCA1MCksIAogICAgICAgICAgICAgICAgIGV4cGFuZCA9IEZBTFNFKSArCiAgICBnZW9tX3NmKGRhdGEgPSBtYXBfZGF0YSwgYWVzKGZpbGwgPSAucHJlZCkpICsKICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPXRvcG8uY29sb3JzKDcpLCBuYS52YWx1ZSA9ICJ0cmFuc3BhcmVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzPWMoMCwxMCwyMCksbGFiZWxzPWMoMCwxMCwyMCksCiAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoMCwyMy41KSwgbmFtZSA9ICJQTSB1Zy9tMyIpICsKICBnZ3RpdGxlKCJQcmVkaWN0ZWQgUE0gMi41IGxldmVscyIpKwogICAgdGhlbWUoYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKQoKcHJlZApgYGAKCk5vdyB3ZSB3aWxsIHVzZSB0aGUgYHBhdGNod29ya2AgcGFja2FnZSB0byBjb21iaW5lIG91ciBsYXN0IHR3byBwbG90cy4gVGhpcyBhbGxvd3MgdXMgdG8gY29tYmluZSBwbG90cyB1c2luZyB0aGUgYCtgIG9yIHRoZSBgL2AgLiBUaGUgYCtgIHdpbGwgcGxhY2UgcGxvdHMgc2lkZSBieSBzaWRlIGFuZCB0aGUgYC9gIHdpbGwgcGxhY2UgcGxvdHMgdG9wIHRvIGJvdHRvbS4KCgpOb3cgbGV0J3MganVzdCBjb21iaW5lIHRoZSB0cnV0aCBwbG90IGFuZCB0aGUgcHJlZGljdGlvbiBwbG90cyB0b2dldGhlcjoKYGBge3J9CnRydXRoL3ByZWQKCmBgYAoKV2UgY2FuIHNlZSB0aGF0IHRoZSBwcmVkaWN0ZWQgZmluZSBwYXJ0aWNsZSBhaXIgcG9sbHV0aW9uIHZhbHVlcyBpbiAodWcvbTMpIGFyZSBxdWl0ZSBzaW1pbGFyIHRvIHRoZSB0cnVlIHZhbHVlcyBtZWFzdXJlZCBieSB0aGUgYWN0dWFsIGdyYXZpbWV0cmljIG1vbml0b3JzLiBXZSBjYW4gYWxzbyBzZWUgdGhhdCBzb3V0aGVybiBDYWxpZm9ybmlhIGhhcyBzb21lIGxhcmdlIGNvdW50aWVzIHdpdGggd29yc2UgcG9sbHV0aW9uIChhcyB0aGV5IGFyZSB5ZWxsb3cgYW5kIHRodXMgaGF2ZSBtdWNoIGhpZ2hlciBwYXJ0aWN1bGF0ZSBtYXR0ZXIgbGV2ZWxzKS4KCkxldCdzIGFkZCBzb21lIHRleHQgdG8gb3VyIHBsb3QgdG8gZXhwbGFpbiBpdCBhIGJpdCBtb3JlLiBXZSBjYW4gZG8gc28gdXNpbmcgdGhlIGBwbG90X2Fubm90YXRpb24oKWAgZnVuY3Rpb24gb2YgdGhlIGBwYXRjaHdvcmtgIHBhY2thZ2UuIFRoZSBgdGhlbWVgIGFyZ3VtZW50IG9mIHRoaXMgZnVuY3Rpb24gdGFrZXMgdGhlIHNhbWUgdGhlbWUgaW5mb3JtYXRpb24gdXNpbmcgdGhlIGB0aGVtZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGdncGxvdDJgIHBhY2thZ2UgYXMgd2hlbiBjcmVhdGluZyBgZ2dwbG90MmBwbG90cy4KCmBgYHtyfQoodHJ1dGgvcHJlZCkgKyBwbG90X2Fubm90YXRpb24odGl0bGUgPSAiTWFjaGluZSBMZWFybmluZyBNZXRob2RzIEFsbG93IGZvciBQcmVkaWN0aW9uIG9mIEFpciBQb2xsdXRpb24iLCBzdWJ0aXRsZSA9ICJBIHJhbmRvbSBmb3Jlc3QgbW9kZWwgcHJlZGljdHMgdHJ1ZSBtb25pdG9yZWQgbGV2ZWxzIG9mIGZpbmUgcGFydGljdWxhdGUgbWF0dGVyIChQTSAyLjUpIGFpciBwb2xsdXRpb24gYmFzZWQgb25cbmRhdGEgYWJvdXQgcG9wdWxhdGlvbiBkZW5zaXR5IGFuZCBvdGhlciBwcmVkaWN0b3JzIHJlYXNvbmFibHkgd2VsbCwgdGh1cyBzdWdnZXN0aW5nIHRoYXQgd2UgY2FuIHByZWRpY3QgbGV2ZWxzXG5vZiBwb2xsdXRpb24gaW4gcGxhY2VzIHdpdGggcG9vciBtb25pdG9yaW5nIiwgdGhlbWUgPSB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPTEyLCBmYWNlID0gImJvbGQiKSwgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpKQoKYGBgCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXZhbD1GQUxTRX0KcG5nKGhlcmU6OmhlcmUoImltZyIsICJtYWluX3Bsb3RfbWFwcy5wbmciKSwgCiAgICBoZWlnaHQgPSAxNTAwLCB3aWR0aCA9IDIwMDAsIHJlcyA9IDMwMCkKKHRydXRoL3ByZWQpICsgcGxvdF9hbm5vdGF0aW9uKHRpdGxlID0gIk1hY2hpbmUgTGVhcm5pbmcgTWV0aG9kcyBBbGxvdyBmb3IgUHJlZGljdGlvbiBvZiBBaXIgUG9sbHV0aW9uIiwgc3VidGl0bGUgPSAiQSByYW5kb20gZm9yZXN0IG1vZGVsIHByZWRpY3RzIHRydWUgbW9uaXRvcmVkIGxldmVscyBvZiBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlciAoUE0gMi41KSBhaXIgcG9sbHV0aW9uIGJhc2VkIG9uXG5kYXRhIGFib3V0IHBvcHVsYXRpb24gZGVuc2l0eSBhbmQgb3RoZXIgcHJlZGljdG9ycyByZWFzb25hYmx5IHdlbGwsIHRodXMgc3VnZ2VzdGluZyB0aGF0IHdlIGNhbiBwcmVkaWN0IGxldmVsc1xub2YgcG9sbHV0aW9uIGluIHBsYWNlcyB3aXRoIHBvb3IgbW9uaXRvcmluZyIsIHRoZW1lID0gdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0xMiwgZmFjZSA9ICJib2xkIiksIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSkKZGV2Lm9mZigpCmBgYAoKIyAqKlN1bW1hcnkqKgoqKioKCiMjIFN5bm9wc2lzCgpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIGV4cGxvcmVkIGdyYXZpbWV0cmljIG1vbml0b3JpbmcgZGF0YSBvZiBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlciBhaXIgcG9sbHV0aW9uIChvdXRjb21lIHZhcmlhYmxlKS4gCk91ciBnb2FsIHdhcyB0byBhYmxlIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbiB3aGVyZSB3ZSBvbmx5IGhhZCBwcmVkaWN0b3IgdmFyaWFibGVzIChvciBmZWF0dXJlcykgd2l0aG91dCBoYXZpbmcgb2JzZXJ2ZWQgYSBjb3JyZXNwb25kaW5nIG1lYXN1cmVtZW50IG9mIGFpciBwb2xsdXRpb24uCgpPdXIgbGVhcm5pbmcgb2JqZWN0aXZlcyB3ZXJlOiAKCi0gSW50cm9kdWNlIGNvbmNlcHRzIGluIG1hY2hpbmUgbGVhcm5pbmcKLSBEZW1vbnN0cmF0ZSBob3cgdG8gYnVpbGQgYSBtYWNoaW5lIGxlYXJuaW5nIG1vZGVsIHdpdGggYHRpZHltb2RlbHNgCi0gRGVtb25zdHJhdGUgaG93IHRvIHZpc3VhbGl6ZSBnZW8tc3BhdGlhbCBkYXRhIHVzaW5nIGBnZ3Bsb3QyYAoKVXNpbmcgdGhlIG1hY2hpbmUgbGVhcm5pbmcgbW9kZWxzIGJ1aWx0IGluIHRoaXMgY2FzZSBzdHVkeSwgd2UgY291bGQgbm93IGV4dGVuZCB0aGlzIG1vZGVsIHRvIGJlIHVzZWQgdG8gcHJlZGljdCBhaXIgcG9sbHV0aW9uIGxldmVscyBpbiBhcmVhcyB3aXRoIHBvb3IgbW9uaXRvcmluZywgdG8gaGVscCBpZGVudGlmeSByZWdpb25zIHdoZXJlIHBvcHVsYXRpb25zIG1heWJlIGVzcGVjaWFsbHkgYXQgcmlzayBmb3IgdGhlIGhlYWx0aCBlZmZlY3RzIG9mIGFpciBwb2xsdXRpb24uICAKCkFuYWx5c2VzIGxpa2UgdGhlIG9uZSBpbiBvdXIgY2FzZSBzdHVkeSBhcmUgaW1wb3J0YW50IGZvciBkZWZpbmluZyB3aGljaCBncm91cHMgY291bGQgYmVuZWZpdCB0aGUgbW9zdCBmcm9tIGludGVydmVudGlvbnMsIGVkdWNhdGlvbiwgYW5kIHBvbGljeSBjaGFuZ2VzIHdoZW4gYXR0ZW1wdGluZyB0byBtaXRpZ2F0ZSBwdWJsaWMgaGVhbHRoIGNoYWxsZW5nZXMuIFlvdSBjYW4gc2VlIGluIHRoaXMgW2FydGljbGVdKGh0dHBzOi8vd3d3Lm5lam0ub3JnL2RvaS9mdWxsLzEwLjEwNTYvTkVKTW9hMTcwMjc0Nyl7dGFyZ2V0PSJfYmxhbmsifSB0aGF0IG1hbnkgYWRkaXRpb25hbCBjb25zaWRlcmF0aW9ucyB3b3VsZCBiZSBpbnZvbHZlZCB0byBhZGVxdWF0ZWx5IHVuZGVyc3RhbmQgdGhlIGRhdGEgZW5vdWdoIHRvIHJlY29tbWVuZCBwb2xpY3kgY2hhbmdlcy4KCkhlcmUgYXJlIHNvbWUgdmlzdWFsIHN1bW1hcmllcyBhYm91dCB3aGF0IHdlIGxlYXJuZWQgYWJvdXQgdXNpbmcgYHRpZHltb2RlbHNgIHRvIHBlcmZvcm0gcHJlZGljdGlvbiBhbmFseXNlcy4KCkZpcnN0IHRoZSBtaW5pbWFsIHN0ZXBzIHJlcXVpcmVkOgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJ0aWR5bW9kZWxzQmFzaWNzLnBuZyIpKQpgYGAKCgpIZXJlIGlzIGEgZ3VpZGUgZm9yIG1vcmUgYWR2YW5jZWQgYW5hbHlzZXMgaW52b2x2aW5nIHByZXByb2Nlc3NpbmcsIGNyb3NzIHZhbGlkYXRpb24sIG9yIHR1bmluZzoKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiZnVsbF90aWR5bW9kZWxzX292ZXJ2aWV3LnBuZyIpKQpgYGAKCgoKCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayBoZXJlIGZvciBtb3JlIG9uIHdoYXQgd2UgbGVhcm5lZCB3aXRoIGB0aWR5bW9kZWxzYCA8L3N1bW1hcnk+CgpIZXJlLCB3ZSBwcm92aWRlIGFuIG92ZXJ2aWV3IG9mIHRoZSBgdGlkeW1vZGVsc2AgZnJhbWV3b3JrLiAKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiZWNvc3lzdGVtLnBuZyIpKQpgYGAKCgpXZSBwZXJmb3JtZWQgdGhlIG1ham9yIHN0ZXBzIG9mIG1hY2hpbmUgbGVhcm5pbmcgdGhhdCB3ZSBpbnRyb2R1Y2VkIGluIHRoZSBiZWdpbm5pbmcgb2YgdGhlIGRhdGEgYW5hbHlzaXM6ICAKCjEuIERhdGEgZXhwbG9yYXRpb24gIAoKV2UgdXNlZCBwYWNrYWdlcyBsaWtlIGBza2ltcmAsIGBzdW1tYXJ5dG9vbHNgLCBgY29ycnBsb3RgLCBhbmQgYEdHYWxseWAgdG8gYmV0dGVyIHVuZGVyc3RhbmQgb3VyIGRhdGEuIFRoZXNlIHBhY2thZ2VzIGNhbiB0ZWxsIHVzIGhvdyBtYW55IG1pc3NpbmcgdmFsdWVzIGVhY2ggdmFyaWFibGUgaGFzIChpZiBhbnkpLCB0aGUgY2xhc3Mgb2YgZWFjaCB2YXJpYWJsZSwgdGhlIGRpc3RyaWJ1dGlvbiBvZiB2YWx1ZXMgZm9yIGVhY2ggdmFyaWFibGUsIHRoZSBzcGFyc2l0eSBvZiBlYWNoIHZhcmlhYmxlLCBhbmQgdGhlIGxldmVsIG9mIGNvcnJlbGF0aW9uIGJldHdlZW4gdmFyaWFibGVzLiAgCgoyLiBEYXRhIHNwbGl0dGluZyAKCldlIHVzZWQgdGhlIGByc2FtcGxlYCBwYWNrYWdlIHRvIGZpcnN0IHBlcmZvcm0gYW4gaW5pdGlhbCBzcGxpdCBvZiBvdXIgZGF0YSBpbnRvIHR3byBwaWVjZXM6IGEgdHJhaW5pbmcgc2V0IGFuZCBhIHRlc3Rpbmcgc2V0LiBUaGUgdHJhaW5pbmcgc2V0IHdhcyB1c2VkIHRvIG9wdGltaXplIHRoZSBtb2RlbCwgd2hpbGUgdGhlIHRlc3Rpbmcgc2V0IHdhcyB1c2VkIG9ubHkgdG8gZXZhbHVhdGUgdGhlIHBlcmZvcm1hbmNlIG9mIG91ciBmaW5hbCBtb2RlbC4gV2UgYWxzbyB1c2VkIHRoZSBgcnNhbXBsZWAgcGFja2FnZSB0byBjcmVhdGUgY3Jvc3MgdmFsaWRhdGlvbiBzdWJzZXRzIG9mIG91ciB0cmFpbmluZyBkYXRhLiBUaGlzIGFsbG93ZWQgdXMgdG8gYmV0dGVyIGFzc2VzcyB0aGUgcGVyZm9ybWFuY2Ugb2Ygb3VyIHRlc3RlZCBtb2RlbHMgdXNpbmcgb3VyIHRyYWluaW5nIGRhdGEuICAKCjMuIFZhcmlhYmxlIGFzc2lnbm1lbnQgYW5kIHByZS1wcm9jZXNzaW5nICAgCgpXZSB1c2VkIHRoZSBgcmVjaXBlc2AgcGFja2FnZSB0byBhc3NpZ24gdmFyaWFibGUgcm9sZXMgKHN1Y2ggYXMgb3V0Y29tZSwgcHJlZGljdG9yLCBhbmQgaWQgdmFyaWFibGUpLiBXZSBhbHNvIHVzZWQgdGhpcyBwYWNrYWdlIHRvIGNyZWF0ZSBhIHJlY2lwZSBmb3IgcHJlLXByb2Nlc3Npbmcgb3VyIHRyYWluaW5nIGFuZCB0ZXN0aW5nIGRhdGEuIFRoaXMgaW52b2x2ZWQgc3RlcHMgc3VjaCBhczogYCBzdGVwX2R1bW15YCB0byBjcmVhdGUgZHVtbXkgbnVtZXJpYyBlbmNvZGluZ3Mgb2Ygb3VyIGNhdGVnb3JpY2FsIHZhcmlhYmxlcywgYHN0ZXBfY29ycmAgdG8gcmVtb3ZlIGhpZ2hseSBjb3JyZWxhdGVkIHZhcmlhYmxlcywgYHN0ZXBfbnp2YCB0byByZW1vdmUgbmVhciB6ZXJvIHZhcmlhbmNlIHZhcmlhYmxlcyB0aGF0IHdvdWxkIGNvbnRyaWJ1dGUgbGl0dGxlIHRvIG91ciBtb2RlbCBhbmQgcG90ZW50aWFsbHkgYWRkIG5vaXNlLiAgV2UgbGVhcm5lZCB0aGF0IG9uY2Ugb3VyIHJlY2lwZSB3YXMgY3JlYXRlZCBhbmQgcHJlcHBlZCB1c2luZyBgcHJlcCgpYHdlIGNvdWxkIGV4dHJhY3QgdGhlIHByZS1wcm9jZXNzZWQgdHJhaW5pbmcgZGF0YSB1c2luZyBganVpY2UoKWAgb3Igb3VyIHByZS1wcm9jZXNzZWQgdGVzdGluZyBkYXRhIHVzaW5nIGBiYWtlKClgLiBXZSBhbHNvIGxlYXJuZWQgdGhhdCBpZiB3ZSB1c2VkIHRoZSBuZXdlciB3b3JrZmxvd3MgcGFja2FnZSB0aGF0IHdlIGRpZCBub3QgbmVlZCB0byB0aGUgYHByZXAoKWAsIGBqdWljZSgpYCwgb3IgYGJha2UoKWAgZnVuY3Rpb25zLCBidXQgdGhhdCBpdCBpcyBzdGlsbCB1c2VmdWwgdG8ga25vdyBob3cgdG8gZG8gc28gaWYgd2Ugd2FudCB0byBsb29rIGF0IG91ciBkYXRhIGFuZCBob3cgdGhlIHJlY2lwZSBpcyBpbmZsdWVuY2luZyBpdCBtb3JlIGRlZXBseS4gIAoKNC4gTW9kZWwgc3BlY2lmaWNhdGlvbiwgZml0dGluZywgdHVuaW5nIGFuZCBwZXJmb3JtYW5jZSBldmFsdWF0aW9uIHVzaW5nIHRoZSB0cmFpbmluZyBkYXRhICAKCldlIGxlYXJuZWQgdGhhdCB0aGUgbW9kZWwgbmVlZHMgdG8gZmlyc3QgYmUgZml0IHRvIHRoZSB0cmFpbmluZyBkYXRhLiBXZSBsZWFybmVkIHRoYXQgaW4gYm90aCBjbGFzc2lmaWNhdGlvbiBhbmQgcHJlZGljdGlvbiwgdGhlIG1vZGVsIGlzIGZpdCB0byB0aGUgdHJhaW5pbmcgZGF0YSBhbmQgdGhlIGV4cGxhbmF0b3J5IHZhcmlhYmxlcyBhcmUgdXNlZCB0byBlc3RpbWF0ZSBudW1lcmljIHZhbHVlcyAoaW4gdGhlIGNhc2Ugb2YgcHJlZGljdGlvbikgb3IgY2F0ZWdvcmljYWwgdmFsdWVzIChpbiB0aGUgY2FzZSBvZiBjbGFzc2lmaWNhdGlvbikgb2YgdGhlIG91dGNvbWUgdmFyaWFibGUgb2YgaW50ZXJlc3QuIFdlIGxlYXJuZWQgdGhhdCB3ZSBzcGVjaWZ5IHRoZSBtb2RlbCBhbmQgaXRzIHNwZWNpZmljYXRpb25zIHVzaW5nIHRoZSBgcGFybnNpcGAgcGFja2FnZSBhbmQgdGhhdCB3ZSBhbHNvIHVzZSB0aGlzIHBhY2thZ2UgdG8gZml0IHRoZSBtb2RlbCB1c2luZyB0aGUgYGZpdCgpYCBmdW5jdGlvbi4gV2UgbGVhcm5lZCB0aGF0IHdlIGlmIGp1c3QgdXNlIGBwYXJzbmlwYCB0byBmaXQgdGhlIG1vZGVsLCB0aGVuIHdlIG5lZWQgdG8gdXNlIHRoZSBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgKG91dHB1dCBmcm9tIGBqdWljZSgpYCkuIFdlIGxlYXJuZWQgdGhhdCB3ZSBjYW4gdXNlIHRoZSByYXcgdHJhaW5pbmcgZGF0YSBpZiB3ZSB1c2UgdGhlIGB3b3JrZmxvd3NgIHBhY2thZ2UgdG8gY3JlYXRlIGEgd29ya2Zsb3cgdGhhdCBwcmUtcHJvY2Vzc2VzIG91ciBkYXRhIGZvciB1cy4gICAKCldlIGxlYXJuZWQgdGhhdCBpZiB0aGUgbW9kZWwgZml0cyB3ZWxsIHRoYW4gdGhlIGVzdGltYXRlZCB2YWx1ZXMgd2lsbCBiZSB2ZXJ5IHNpbWlsYXIgdG8gdGhlIHRydWUgb3V0Y29tZSB2YXJpYWJsZSB2YWx1ZXMgaW4gb3VyIHRyYWluaW5nIGRhdGEuIFdlIGxlYXJuZWQgdGhhdCB3ZSBjYW4gYXNzZXNzIG1vZGVsIHBlcmZvcm1hbmNlIHVzaW5nIHRoZSBgeWFyZHN0aWNrYCBwYWNrYWdlIHdpdGggdGhlIGBtZXRyaWNzYCBmdW5jdGlvIG9yIHRoZSBgdHVuZWAgcGFja2FnZSBhbmQgdGhlIGBjb2xsZWN0X21ldHJpY3MoKWAgZnVuY3Rpb24gKHJlcXVpcmVkIGlmIHVzaW5nIGNyb3NzIHZhbGlkYXRpb24gb3IgdHVuaW5nKS4gV2UgYWxzbyBsZWFybmVkIHRoYXQgd2UgY2FuIHVzZSBzdWJzZXRzIG9mIG91ciB0cmFpbmluZyBkYXRhICh3aGljaCB3ZSBjcmVhdGVkIHdpdGggdGhlIGByc2FtcGxlYCBwYWNrYWdlKSB0byBwZXJmb3JtIGNyb3NzIHZhbGlkYXRpb24gdG8gZ2V0IGEgYmV0dGVyIGVzdGltYXRlIGFib3V0IHRoZSBwZXJmb3JtYW5jZSBvZiBvdXIgbW9kZWwgdXNpbmcgb3VyIHRyYWluaW5nIGRhdGEsIGFzIHdlIHdhbnQgb3VyIHJlc3VsdHMgdG8gYmUgZ2VuZXJhbGl6YWJsZSBhbmQgdG8gcGVyZm9ybSB3ZWxsIHdpdGggb3RoZXIgZGF0YSwgbm90IGp1c3Qgb3VyIHRyYWluaW5nIGRhdGEuIFdlIHVzZWQgdGhlIGBmaXRfcmVzYW1wbGVzKClgIGZ1bmN0aW9uIG9mIHRoZSB0dW5lIHBhY2thZ2UgdG8gZml0IG91ciBtb2RlbCBvbiBvdXIgZGlmZmVyZW50IHRyYWluaW5nIGRhdGEgc3Vic2V0cyBhbmQgdGhlIGBjb2xsZWN0X21ldHJpY3MoKWAgZnVuY3Rpb24gKGFsc28gb2YgdGhlIGB0dW5lYCBwYWNrYWdlKSB0byBldmFsdWF0ZSBtb2RlbCBwZXJmb3JtYW5jZSB1c2luZyB0aGVzZSBzdWJzZXRzLiAgV2UgYWxzbyBsZWFybmVkIHRoYXQgd2UgY2FuIHBvdGVudGlhbGx5IGltcHJvdmUgbW9kZWwgcGVyZm9ybWFuY2UgYnkgdHVuaW5nIGFzcGVjdHMgYWJvdXQgdGhlIG1vZGVsIGNhbGxlZCBbaHlwZXJwYXJhbWV0ZXJzXShodHRwczovL21hY2hpbmVsZWFybmluZ21hc3RlcnkuY29tL2RpZmZlcmVuY2UtYmV0d2Vlbi1hLXBhcmFtZXRlci1hbmQtYS1oeXBlcnBhcmFtZXRlci8pe3RhcmdldD0iX2JsYW5rIn0gdG8gZGV0ZXJtaW5lIHRoZSBiZXN0IG9wdGlvbiBmb3IgbW9kZWwgcGVyZm9ybWFuY2UuIFdlIGxlYXJuZWQgdGhhdCB3ZSBjYW4gZG8gdGhpcyB1c2luZyB0aGUgYHR1bmVgIGFuZCBgZGlhbHNgIHBhY2thZ2VzIGFuZCBldmFsdWF0aW5nIHRoZSBwZXJmb3JtYW5jZSBvZiBvdXIgbW9kZWwgd2l0aCB0aGUgZGlmZmVyZW50IGh5cGVycGFyYW1ldGVyIG9wdGlvbnMgYW5kIG91ciB0cmFpbmluZyBkYXRhIHN1YnNldHMgdGhhdCB3ZSB1c2VkIGZvciBjcm9zcyB2YWxpZGF0aW9uLiBBZnRlciB3ZSB0ZXN0ZWQgc2V2ZXJhbCBkaWZmZXJlbnQgbWV0aG9kcyB0byBtb2RlbCBvdXIgZGF0YSwgd2UgY29tcGFyZWQgdGhlbSB0byBjaG9vc2UgdGhlIGJlc3QgcGVyZm9ybWluZyBtb2RlbCBhcyBvdXIgZmluYWwgbW9kZWwuICAKCgo1LiBPdmVyYWxsIG1vZGVsIHBlcmZvcm1hbmNlIGV2YWx1YXRpb24gIAoKT25jZSB3ZSBjaG9zZSBvdXIgZmluYWwgbW9kZWwsIHdlIGV2YWx1YXRlZCB0aGUgZmluYWwgbW9kZWwgcGVyZm9ybWFuY2UgdXNpbmcgdGhlIHRlc3RpbmcgZGF0YSB1c2luZyB0aGUgYGxhc3RfZml0KClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZS4gVGhpcyBnaXZlcyB1cyBhIGJldHRlciBlc3RpbWF0ZSBhYm91dCBob3cgd2VsbCB0aGUgbW9kZWwgd2lsbCBwcmVkaWN0IG9yIGNsYXNzaWZ5IHRoZSBvdXRjb21lIHZhcmlhYmxlIG9mIGludGVyZXN0IHdpdGggbmV3IGluZGVwZW5kZW50IGRhdGEuIElkZWFsbHkgb25lIHdvdWxkIGFsc28gcGVyZm9ybSBhbiBldmFsdWF0aW9uIHdpdGggaW5kZXBlbmRlbnQgZGF0YSB0byBwcm92aWRlIGEgc2Vuc2Ugb2YgaG93IGdlbmVyYWxpemFibGUgdGhlIG1vZGVsIGlzIHRvIG90aGVyIGRhdGEgc291cmNlcy4gCgpXZSBhbHNvIHNhdyB0aGF0IHdlIGNhbiB1c2UgdGhlIGBjb2xsZWN0X3ByZWRpY3Rpb25zKClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZSB0byBnZXQgdGhlIHByZWRpY3Rpb25zIGZvciBvdXIgdGVzdCBkYXRhLiBXZSBzYXcgdGhhdCB3ZSBjYW4gZ2V0IG1vcmUgZGV0YWlsZWQgcHJlZGljdGlvbiBkYXRhIHVzaW5nIHRoZSBgcHJlZGljdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHBhcnNuaXBgIHBhY2thZ2UuCgo8L2RldGFpbHM+CgoKCiMjIFN1Z2dlc3RlZCBIb21ld29yawoKU3R1ZGVudHMgY2FuIHByZWRpY3QgYWlyIHBvbGx1dGlvbiBtb25pdG9yIHZhbHVlcyB1c2luZyBhIGRpZmZlcmVudCBhbGdvcml0aG0gYW5kIHByb3ZpZGUgYW4gZXhwbGFuYXRpb24gZm9yIGhvdyB0aGF0IGFsZ29yaXRobSB3b3JrcyBhbmQgd2h5IGl0IG1heSBiZSBhIGdvb2QgY2hvaWNlIGZvciBtb2RlbGluZyB0aGlzIGRhdGEuCgoKIyAqKkFkZGl0aW9uYWwgSW5mb3JtYXRpb24qKgoqKioKCiMjIEhlbHBmdWwgTGlua3MKCjEuIEEgcmV2aWV3IG9mIFt0aWR5bW9kZWxzXShodHRwczovL3J2aWV3cy5yc3R1ZGlvLmNvbS8yMDE5LzA2LzE5L2EtZ2VudGxlLWludHJvLXRvLXRpZHltb2RlbHMvKXt0YXJnZXQ9Il9ibGFuayJ9ICAKMi4gQSBbY291cnNlIG9uIHRpZHltb2RlbHNdKGh0dHBzOi8vanVsaWFzaWxnZS5jb20vYmxvZy90aWR5bW9kZWxzLW1sLWNvdXJzZS8pe3RhcmdldD0iX2JsYW5rIn0gYnkgSnVsaWEgU2lsZ2UgIAozLiBbTW9yZSBleGFtcGxlcywgZXhwbGFuYXRpb25zLCBhbmQgaW5mbyBhYm91dCB0aWR5bW9kZWxzIGRldmVsb3BtZW50XShodHRwczovL3d3dy50aWR5bW9kZWxzLm9yZy9sZWFybi8pe3RhcmdldD0iX2JsYW5rIn0gZnJvbSB0aGUgZGV2ZWxvcGVycyAgCjQuIEEgZ3VpZGUgZm9yIFtwcmUtcHJvY2Vzc2luZyB3aXRoIHJlY2lwZXNdKGh0dHA6Ly93d3cucmViZWNjYWJhcnRlci5jb20vYmxvZy8yMDE5LTA2LTA2X3ByZV9wcm9jZXNzaW5nLyl7dGFyZ2V0PSJfYmxhbmsifSAgCjUuIEEgW2d1aWRlXShodHRwczovL2JyaWF0dGUuZ2l0aHViLmlvL2dnY29yci8pe3RhcmdldD0iX2JsYW5rIn0gZm9yIHVzaW5nIEdHYWxseSB0byBjcmVhdGUgY29ycmVsYXRpb24gcGxvdHMgIAo2LiBBIFtndWlkZV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy9ibG9nLzIwMTgvMTEvcGFyc25pcC0wLTAtMS8pe3RhcmdldD0iX2JsYW5rIn0gZm9yIHVzaW5nIHBhcnNuaXAgdG8gdHJ5IGRpZmZlcmVudCBhbGdvcml0aG1zIG9yIGVuZ2luZXMgIAo3LiBBIFtsaXN0IG9mIHJlY2lwZSBmdW5jdGlvbnNdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcmVjaXBlcy9yZWZlcmVuY2UvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgCjguIEEgZ3JlYXQgYmxvZyBwb3N0IGFib3V0IFtjcm9zcyB2YWxpZGF0aW9uXShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vdHJhaW4tdGVzdC1zcGxpdC1hbmQtY3Jvc3MtdmFsaWRhdGlvbi1pbi1weXRob24tODBiNjFiZWNhNGI2KXt0YXJnZXQ9Il9ibGFuayJ9ICAKOS4gQSBkaXNjdXNzaW9uIGFib3V0IFtldmFsdWF0aW5nIG1vZGVsIHBlcmZvcm1hbmNlXShodHRwczovL21lZGl1bS5jb20vQGxpbWF2YWxsYW50aW4vbWV0cmljcy10by1tZWFzdXJlLW1hY2hpbmUtbGVhcm5pbmctbW9kZWwtcGVyZm9ybWFuY2UtZThjOTYzNjY1NDc2KXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBhIGRlZXBlciBleHBsYW5hdGlvbiBhYm91dCBob3cgdG8gZXZhbHVhdGUgbW9kZWwgcGVyZm9ybWFuY2UgIAoxMC4gW1JTdHVkaW8gY2hlYXRzaGVldHNdKGh0dHBzOi8vcnN0dWRpby5jb20vcmVzb3VyY2VzL2NoZWF0c2hlZXRzLyl7dGFyZ2V0PSJfYmxhbmsifQoxMS4gQW4gW2V4cGxhbmF0aW9uXShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vc3VwZXJ2aXNlZC12cy11bnN1cGVydmlzZWQtbGVhcm5pbmctMTRmNjhlMzJlYThkKXt0YXJnZXQ9Il9ibGFuayJ9IG9mIHN1cGVydmlzZWQgdnMgdW5zdXBlcnZpc2VkIG1hY2hpbmUgbGVhcm5pbmcgYW5kIGJpYXMtdmFyaWFuY2UgdHJhZGUtb2ZmLgoxMi4gQSB0aG9yb3VnaCBbZXhwbGFuYXRpb25dKGh0dHBzOi8vcm95YWxzb2NpZXR5cHVibGlzaGluZy5vcmcvZG9pLzEwLjEwOTgvcnN0YS4yMDE1LjAyMDIjOn46dGV4dD1QcmluY2lwYWwlMjBjb21wb25lbnQlMjBhbmFseXNpcyUyMChQQ0EpJTIwaXMsdmFyaWFibGVzJTIwdGhhdCUyMHN1Y2Nlc3NpdmVseSUyMG1heGltaXplJTIwdmFyaWFuY2UuKXt0YXJnZXQ9Il9ibGFuayJ9IG9mIHByaW5jaXBhbCBjb21wb25lbnQgYW5hbHlzaXMuCjEzLiBJZiB5b3UgaGF2ZSBhY2Nlc3MsIHRoaXMgaXMgYSBncmVhdCBbZGlzY3Vzc2lvbl0oaHR0cHM6Ly93d3cudGFuZGZvbmxpbmUuY29tL2RvaS9hYnMvMTAuMTA4MC8wMDAzMTMwNS4xOTg0LjEwNDgzMTgzKXt0YXJnZXQ9Il9ibGFuayJ9ICBhYm91dCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGluZGVwZW5kZW5jZSwgb3J0aG9nb25hbGl0eSwgYW5kIGxhY2sgb2YgY29ycmVsYXRpb24uCjE0LiBHcmVhdCBbdmlkZW8gZXhwbGFuYXRpb25dKGh0dHBzOi8veW91dHUuYmUvX1VWSG5lQlVCVzApe3RhcmdldD0iX2JsYW5rIn0gb2YgUENBLiAgCgo8dT5UZXJtcyBhbmQgY29uY2VwdHMgY292ZXJlZDo8L3U+ICAKCltUaWR5dmVyc2VdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0ltcHV0YXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0ltcHV0YXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW1RyYW5zZm9ybWF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EYXRhX3RyYW5zZm9ybWF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAgCltEaXNjcmV0aXphdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRGlzY3JldGl6YXRpb25fb2ZfY29udGludW91c19mZWF0dXJlcyl7dGFyZ2V0PSJfYmxhbmsifSAgCltEdW1teSBWYXJpYWJsZXNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0R1bW15X3ZhcmlhYmxlXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAgCltPbmUgSG90IEVuY29kaW5nXShodHRwczovL21hY2hpbmVsZWFybmluZ21hc3RlcnkuY29tL3doeS1vbmUtaG90LWVuY29kZS1kYXRhLWluLW1hY2hpbmUtbGVhcm5pbmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0RhdGEgVHlwZSBDb252ZXJzaW9uc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2hhYmxhci92aWduZXR0ZXMvY29udmVydC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0ludGVyYWN0aW9uXShodHRwczovL3N0YXRpc3RpY3NieWppbS5jb20vcmVncmVzc2lvbi9pbnRlcmFjdGlvbi1lZmZlY3RzLyl7dGFyZ2V0PSJfYmxhbmsifSAgCltOb3JtYWxpemF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Ob3JtYWxpemF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAgCltEaW1lbnNpb25hbGl0eSBSZWR1Y3Rpb24vU2lnbmFsIEV4dHJhY3Rpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0RpbWVuc2lvbmFsaXR5X3JlZHVjdGlvbil7dGFyZ2V0PSJfYmxhbmsifSAgCltSb3cgT3BlcmF0aW9uc10oaHR0cHM6Ly90YXJ0YXJ1cy5vcmcvZ2FyZXRoL21hdGhzL0xpbmVhcl9BbGdlYnJhL3Jvd19vcGVyYXRpb25zLnBkZil7dGFyZ2V0PSJfYmxhbmsifSAgCltOZWFyIFplcm8gVmFyYWluY2VdKGh0dHBzOi8vd3d3LnItYmxvZ2dlcnMuY29tL25lYXItemVyby12YXJpYW5jZS1wcmVkaWN0b3JzLXNob3VsZC13ZS1yZW1vdmUtdGhlbS8pe3RhcmdldD0iX2JsYW5rIn0gIApbUGFyYW1ldGVycyBhbmQgSHlwZXJwYXJhbWV0ZXJzXShodHRwczovL21hY2hpbmVsZWFybmluZ21hc3RlcnkuY29tL2RpZmZlcmVuY2UtYmV0d2Vlbi1hLXBhcmFtZXRlci1hbmQtYS1oeXBlcnBhcmFtZXRlci8pe3RhcmdldD0iX2JsYW5rIn0gICAKW1N1cGVydmlzZWQgYW5kIFVuc3BlcnZpc2VkIExlYXJuaW5nXShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vc3VwZXJ2aXNlZC12cy11bnN1cGVydmlzZWQtbGVhcm5pbmctMTRmNjhlMzJlYThkKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW1ByaW5jaXBhbCBDb21wb25lbnQgQW5hbHlzaXNdKGh0dHBzOi8vbWVkaXVtLmNvbS9Ac2F2YXN0YW1pcmtvL3BjYS1hLWxpbmVhci10cmFuc2Zvcm1hdGlvbi1mOGFhY2Q0ZWIwMDcpe3RhcmdldD0iX2JsYW5rIn0gIApbTGluZWFyIENvbWJpbmF0aW9uc10oaHR0cHM6Ly93d3cubWF0aGJvb3RjYW1wcy5jb20vbGluZWFyLWNvbWJpbmF0aW9ucy12ZWN0b3JzLyl7dGFyZ2V0PSJfYmxhbmsifSAgCltEZWNpc2lvbiBUcmVlXShodHRwczovL21lZGl1bS5jb20vZ3JleWF0b20vZGVjaXNpb24tdHJlZXMtYS1zaW1wbGUtd2F5LXRvLXZpc3VhbGl6ZS1hLWRlY2lzaW9uLWRjNTA2YTQwM2FlYil7dGFyZ2V0PSJfYmxhbmsifSAgCltSYW5kb20gRm9yZXN0XShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vZGVjaXNpb24tdHJlZS1lbnNlbWJsZXMtYmFnZ2luZy1hbmQtYm9vc3RpbmctMjY2YThiYTYwZmQ5KXt0YXJnZXQ9Il9ibGFuayJ9ICAKCgogPHU+KipQYWNrYWdlcyB1c2VkIGluIHRoaXMgY2FzZSBzdHVkeToqKiA8L3U+CgpQYWNrYWdlICAgfCBVc2UgaW4gdGhpcyBjYXNlIHN0dWR5ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAotLS0tLS0tLS0tIHwtLS0tLS0tLS0tLS0tCltoZXJlXShodHRwczovL2dpdGh1Yi5jb20vamVubnliYy9oZXJlX2hlcmUpe3RhcmdldD0iX2JsYW5rIn0gICAgICAgfCB0byBlYXNpbHkgbG9hZCBhbmQgc2F2ZSBkYXRhCltyZWFkcl0oaHR0cHM6Ly9yZWFkci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gaW1wb3J0IHRoZSBDU1YgZmlsZSBkYXRhCltkcGx5cl0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gdmlldy9hcnJhbmdlL2ZpbHRlci9zZWxlY3QvY29tcGFyZSBzcGVjaWZpYyBzdWJzZXRzIG9mIHRoZSBkYXRhIApbc2tpbXJdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9za2ltci9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBnZXQgYW4gb3ZlcnZpZXcgb2YgZGF0YQpbc3VtbWFyeXRvb2xzXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2tpbXIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIGRhdGEgaW4gYSBkaWZmZXJlbnQgc3R5bGUKW21hZ3JpdHRyXShodHRwczovL21hZ3JpdHRyLnRpZHl2ZXJzZS5vcmcvYXJ0aWNsZXMvbWFncml0dHIuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gdXNlIHRoZSBgJTw+JWAgcGlwcGluZyBvcGVyYXRvciAKW2NvcnJwbG90XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvY29ycnBsb3QvdmlnbmV0dGVzL2NvcnJwbG90LWludHJvLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBtYWtlIGxhcmdlIGNvcnJlbGF0aW9uIHBsb3RzCltHR2FsbHldKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9HR2FsbHkvR0dhbGx5LnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIG1ha2Ugc21hbGxlciBjb3JyZWxhdGlvbiBwbG90cyAgCltyc2FtcGxlXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JzYW1wbGUvYXJ0aWNsZXMvQmFzaWNzLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHNwbGl0IHRoZSBkYXRhIGludG8gdGVzdGluZyBhbmQgdHJhaW5pbmcgc2V0cyBhbmQgdG8gc3BsaXQgdGhlIHRyYWluaW5nIHNldCBmb3IgY3Jvc3MtdmFsaWRhdGlvbiAgCltyZWNpcGVzXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JlY2lwZXMvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBwcmUtcHJvY2VzcyBkYXRhIGZvciBtb2RlbGluZyBpbiBhIHRpZHkgYW5kIHJlcHJvZHVjaWJsZSB3YXkgYW5kIHRvIGV4dHJhY3QgcHJlLXByb2Nlc3NlZCBkYXRhIChtYWpvciBmdW5jdGlvbnMgYXJlIGByZWNpcGUoKWAgLCBgcHJlcCgpYCBhbmQgdmFyaW91cyB0cmFuc2Zvcm1hdGlvbiBgc3RlcF8qKClgIGZ1bmN0aW9ucywgYXMgd2VsbCBhcyBganVpY2UoKWAgLSBleHRyYWN0cyBmaW5hbCBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgYW5kIGBiYWtlKClgIC0gYXBwbGllcyByZWNpcGUgc3RlcHMgdG8gdGVzdGluZyBkYXRhKS4gU2VlIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmVjaXBlcy9yZWNpcGVzLnBkZil7dGFyZ2V0PSJfYmxhbmsifSAgZm9yIG1vcmUgaW5mby4KW3BhcnNuaXBdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcGFyc25pcC8pe3RhcmdldD0iX2JsYW5rIn0gICB8IGFuIGludGVyZmFjZSB0byBjcmVhdGUgbW9kZWxzIChtYWpvciBmdW5jdGlvbnMgYXJlICBgZml0KClgLCBgc2V0X2VuZ2luZSgpYCkKW3lhcmRzdGlja10oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby95YXJkc3RpY2svKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBldmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2YgbW9kZWxzClticm9vbV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy9ibG9nLzIwMTgvMDcvYnJvb20tMC01LTAvKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gZ2V0IHRpZHkgb3V0cHV0IGZvciBvdXIgbW9kZWwgZml0IGFuZCBwZXJmb3JtYW5jZQpbZ2dwbG90Ml0oaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIHwgdG8gbWFrZSB2aXN1YWxpemF0aW9ucyB3aXRoIG11bHRpcGxlIGxheWVycwpbZGlhbHNdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvYmxvZy8yMDE5LzEwL2RpYWxzLTAtMC0zLyl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHNwZWNpZnkgaHlwZXItcGFyYW1ldGVyIHR1bmluZwpbdHVuZV0oaHR0cHM6Ly90dW5lLnRpZHltb2RlbHMub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHBlcmZvcm0gY3Jvc3MgdmFsaWRhdGlvbiwgdHVuZSBoeXBlci1wYXJhbWV0ZXJzLCBhbmQgZ2V0IHBlcmZvcm1hbmNlIG1ldHJpY3MKW3dvcmtmbG93c10oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL3dvcmtmbG93cy92ZXJzaW9ucy8wLjEuMSl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGNyZWF0ZSBtb2RlbGluZyB3b3JrZmxvdyB0byBzdHJlYW1saW5lIHRoZSBtb2RlbGluZyBwcm9jZXNzClt2aXBdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy92aXAvdmlwLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGNyZWF0ZSB2YXJpYWJsZSBpbXBvcnRhbmNlIHBsb3RzCltyYW5kb21Gb3Jlc3RdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yYW5kb21Gb3Jlc3QvcmFuZG9tRm9yZXN0LnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHBlcmZvcm0gdGhlIHJhbmRvbSBmb3Jlc3QgYW5hbHlzaXMKW2RvUGFyYWxsZWxdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9kb1BhcmFsbGVsL2RvUGFyYWxsZWwucGRmKSB8IHRvIGZpdCBjcm9zcyB2YWxpZGF0aW9uIHNhbXBsZXMgaW4gcGFyYWxsZWwgCltzdHJpbmdyXShodHRwczovL3N0cmluZ3IudGlkeXZlcnNlLm9yZy9hcnRpY2xlcy9zdHJpbmdyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgfCB0byBtYW5pcHVsYXRlIHRoZSB0ZXh0IHRoZSBtYXAgZGF0YQpbdGlkeXJdKGh0dHBzOi8vdGlkeXIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIHNlcGFyYXRlIGRhdGEgd2l0aGluIGEgY29sdW1uIGludG8gbXVsdGlwbGUgY29sdW1ucwpbcm5hdHVyYWxlYXJ0aF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JuYXR1cmFsZWFydGgvUkVBRE1FLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBnZXQgdGhlIGdlb21ldHJ5IGRhdGEgZm9yIHRoZSBlYXJ0aCB0byBwbG90IHRoZSBVUwpbbWFwc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hcHMvbWFwcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBnZXQgbWFwIGRhdGFiYXNlIGRhdGEgYWJvdXQgY291bnRpZXMgdG8gZHJhdyB0aGVtIG9uIG91ciBVUyBtYXAKW3NmXShodHRwczovL3Itc3BhdGlhbC5naXRodWIuaW8vc2YvKXt0YXJnZXQ9Il9ibGFuayJ9ICB8IHRvIGNvbnZlcnQgdGhlIG1hcCBkYXRhIGludG8gYSBkYXRhIGZyYW1lCltsd2dlb21dKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9sd2dlb20vbHdnZW9tLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHVzZSB0aGUgYHNmYCBmdW5jdGlvbiB0byBjb252ZXJ0IHRoZSBtYXAgZ2VvZ3JhcGhpY2FsIGRhdGEKW3JnZW9zXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmdlb3Mvcmdlb3MucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gdXNlIGdlb21ldHJ5IGRhdGEKW3BhdGNod29ya10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3BhdGNod29yay9wYXRjaHdvcmsucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gYWxsb3cgcGxvdHMgdG8gYmUgY29tYmluZWQKCgojIyBTZXNzaW9uIGluZm8gCgoKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCgoKIyMgQWNrbm93bGVkZ2VtZW50cwoKCldlIHdvdWxkIGxpa2UgdG8gYWNrbm93bGVkZ2UgW1JvZ2VyIFBlbmddKGh0dHA6Ly93d3cuYmlvc3RhdC5qaHNwaC5lZHUvfnJwZW5nLyksIFtNZWdhbiBMYXRzaGF3XShodHRwczovL3d3dy5qaHNwaC5lZHUvZmFjdWx0eS9kaXJlY3RvcnkvcHJvZmlsZS8xNzA4L21lZ2FuLXdlaWwtbGF0c2hhdyksIGFuZCBbS2lyc3RlbiBLb2VobGVyXShodHRwczovL3d3dy5qaHNwaC5lZHUvZmFjdWx0eS9kaXJlY3RvcnkvcHJvZmlsZS8yOTI4L2tpcnN0ZW4ta29laGxlcikgZm9yIGFzc2lzdGluZyBpbiBmcmFtaW5nIHRoZSBtYWpvciBkaXJlY3Rpb24gb2YgdGhlIGNhc2Ugc3R1ZHkuCgpXZSB3b3VsZCBhbHNvIGxpa2UgdG8gYWNrbm93bGVkZ2UgdGhlIFtCbG9vbWJlcmcgQW1lcmljYW4gSGVhbHRoIEluaXRpYXRpdmVdKGh0dHBzOi8vYW1lcmljYW5oZWFsdGguamh1LmVkdS8pIGZvciBmdW5kaW5nIHRoaXMgd29yay4gCg==